SharePoint自动化系列——Solution auto-redeploy using Selenium(C#)
轉載請注明出自天外歸云的博客園:http://www.cnblogs.com/LanTianYou/
本來的想法是做一個可以自動卸載并且部署新solution到SharePoint farm的tool。但是最后只做到retract成功和remove solution之前這個階段。因為一個原因(等待solution retracted的過程中出現CLR方面的問題)導致不能將整個過程連續起來,這是相關的博問,希望有高手可以解惑。
下面的tool將會根據SharePoint solution wsp文件名自動識別solution,并在相應的站點deactive相應的site collection級別的solution feature,然后在SharePoint farm中卸載相應的solution。
圖形界面:
選擇Web Application,選擇其下的Site Collection,然后填寫登陸SharePoint Site的用戶名和密碼,選擇要卸載的wsp文件。之后點擊OK,就會自動進行卸載。
待完成的部分(已經都注釋掉了)用是從等待retract成功開始,然后remove solution,deploy solution,以及active feature的過程。難點主要是等待solution retract成功。希望SharePoint方面專家可以幫助解決這個問題。相關的詳細異常信息,請見博問。
代碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using System.IO; using OpenQA.Selenium; using OpenQA.Selenium.IE; using OpenQA.Selenium.Support; using OpenQA.Selenium.Support.UI; using Selenium; using System.Net; using System.Runtime.InteropServices; using System.Globalization;namespace SharePoint_Solution_Auto_Deploy {public partial class MainForm : Form{//To make the GetForegroundWindow possible.[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]public static extern IntPtr GetForegroundWindow();//Form entry.public MainForm(){InitializeComponent();getSPWebApps(); }//Add web apps to the combobox.private void getSPWebApps(){try{SPSecurity.RunWithElevatedPrivileges(() =>{foreach (SPWebApplication webApp in SPWebService.ContentService.WebApplications){WebAppComBox.Items.Add(webApp.Name);}});}catch (Exception ex){WriteLog(ex);}}//Web application.private void WebAppsComBox_SelectedIndexChanged(object sender, EventArgs e){WebAppComBox.Text = WebAppComBox.SelectedItem.ToString();SPWebApplicationCollection webApps = SPWebService.ContentService.WebApplications;SPWebApplication webApp = webApps[WebAppComBox.Text];getSPSites(webApp);}//Site.private void getSPSites(SPWebApplication webApp){SPSiteCollection sites = webApp.Sites;//Clear old items from the combox first and then add the new items into it. SiteComBox.Items.Clear();foreach (SPSite site in sites){SiteComBox.Items.Add(site.Url.ToString());}}//Write log method.private static void WriteLog(Exception ex){string logUrl = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\SeleniumAutoTest.txt";if (File.Exists(@logUrl)){using (FileStream fs = new FileStream(logUrl, FileMode.Append)){using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)){try{sw.Write(ex);}catch (Exception ex1){WriteLog(ex1);}finally{sw.Close();fs.Close();}}}}else{using (FileStream fs = new FileStream(logUrl, FileMode.CreateNew)){using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)){try{sw.Write(ex);}catch (Exception ex1){WriteLog(ex1);}finally{sw.Close();fs.Close();}}}}}//Select the wsp file action.private void select_wsp_button_Click(object sender, EventArgs e){OpenFileDialog wspFile = new OpenFileDialog();if (wspFile.ShowDialog() == DialogResult.OK) {WspText.Text = wspFile.FileName;}}//Retract and deploy action.private void ok_button_Click(object sender, EventArgs e){//1.Login site and deactive the feature.IWebDriver iw = new InternetExplorerDriver();iw = login(iw, SiteComBox.Text.ToString(), UserNameText.Text.ToString(), PwdText.Text.ToString());INavigation navi = iw.Navigate();//Go to the site collection features page.navi.GoToUrl(SiteComBox.Text.ToString() + "/_layouts/15/ManageFeatures.aspx?Scope=Site");//Judge the feature category by the name wsp file selected.string category;var wspPath = WspText.Text.ToString().Split(new Char[] { '\\' });category = wspPath[wspPath.Count() - 1];//MessageBox.Show(category.ToString());//Deactive the feature. deactivateFeature(iw, category);//2.If has solution, retract first.string solutionPageUrl = "http://wdsinpexca:10000/_admin/Solutions.aspx";navi.GoToUrl(solutionPageUrl);iw.FindElement(By.LinkText(category.ToLower())).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRetractSolution_LinkText");iw.FindElement(By.Id("ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRetractSolution_LinkText")).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_ctl02_RptControls_BtnSubmit");iw.FindElement(By.Id("ctl00_PlaceHolderMain_ctl02_RptControls_BtnSubmit")).Click();//During the retracting period, there will be a down. Let's sleep to get over it.//Thread.Sleep(300000);//Back to the wsp page. iw.FindElement(By.LinkText(category.ToLower())).Click();iw.Navigate().Refresh();//Wait for the solution retracted.//waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRemoveSolution_LinkText");//iw.FindElement(By.Id("ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRemoveSolution_LinkText")).Click();//Click OK in the popup window.//IntPtr myPtr = GetForegroundWindow();//if (myPtr != IntPtr.Zero)//{// System.Windows.Forms.SendKeys.SendWait("{ENTER}");//}//3.Deploy the solution to the web app.//4.Active the site wsp feature. }//Deactive the feature accourding to the wsp solution category.private void deactivateFeature(IWebDriver iw,string category){if (category == "APPSSP2013MISite.wsp"){//Deactive the MISITE feature.waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_divFeatureStatus");string featureStatus = iw.FindElement(By.Id("ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_divFeatureStatus")).GetAttribute("featurestatus").ToString();if (featureStatus == "Active"){waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_btnActivate");iw.FindElement(By.Id("ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_btnActivate")).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_lnkbtnDeactivate");iw.FindElement(By.Id("ctl00_PlaceHolderMain_lnkbtnDeactivate")).Click();}}//Other solutions can be extended here. }//Wait until page-element loaded method.private static void waitUntilPageLoaded(IWebDriver iw, string element){try{iw.FindElement(By.Id(element));}catch (Exception ex){WriteLog(ex);//Refresh the current page.//iw.Navigate().Refresh();Thread.Sleep(1000);waitUntilPageLoaded(iw, element);}}//Login SP site method.public static IWebDriver login(IWebDriver driver, string url,string userName,string pwd){INavigation navigation = driver.Navigate();navigation.GoToUrl(url);//driver.FindElement(By.Id("overridelink")).Click();IntPtr myPtr = GetForegroundWindow();//IntPtr hWnd = FindWindow(null, "abc");if (myPtr != IntPtr.Zero){//Send message to the window. System.Windows.Forms.SendKeys.SendWait(userName);System.Windows.Forms.SendKeys.SendWait("{TAB}");System.Windows.Forms.SendKeys.SendWait(pwd);System.Windows.Forms.SendKeys.SendWait("{ENTER}");}return driver;}} } View Code因為不知道怎么一氣呵成,于是我把Retract和Retract之后的事情拆開來做,就有了下面的:
代碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.SharePoint; using Microsoft.SharePoint.Administration; using System.IO; using OpenQA.Selenium; using OpenQA.Selenium.IE; using OpenQA.Selenium.Support; using OpenQA.Selenium.Support.UI; using Selenium; using System.Net; using System.Runtime.InteropServices; using System.Globalization; using System.Management.Automation; using System.Management.Automation.Runspaces;namespace SharePoint_Solution_Auto_Deploy {public partial class MainForm : Form{//To make the GetForegroundWindow possible.[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]public static extern IntPtr GetForegroundWindow();//Form entry.public MainForm(){InitializeComponent();getSPWebApps(); }//Add web apps to the combobox.private void getSPWebApps(){try{SPSecurity.RunWithElevatedPrivileges(() =>{foreach (SPWebApplication webApp in SPWebService.ContentService.WebApplications){WebAppComBox.Items.Add(webApp.Name);}});}catch (Exception ex){WriteLog(ex);}}//Web application.private void WebAppsComBox_SelectedIndexChanged(object sender, EventArgs e){WebAppComBox.Text = WebAppComBox.SelectedItem.ToString();SPWebApplicationCollection webApps = SPWebService.ContentService.WebApplications;SPWebApplication webApp = webApps[WebAppComBox.Text];getSPSites(webApp);}//Site.private void getSPSites(SPWebApplication webApp){SPSiteCollection sites = webApp.Sites;//Clear old items from the combox first and then add the new items into it. SiteComBox.Items.Clear();foreach (SPSite site in sites){SiteComBox.Items.Add(site.Url.ToString());}}//Write log method.private static void WriteLog(Exception ex){string logUrl = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\SeleniumAutoTest.txt";if (File.Exists(@logUrl)){using (FileStream fs = new FileStream(logUrl, FileMode.Append)){using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)){try{sw.Write(ex);}catch (Exception ex1){WriteLog(ex1);}finally{sw.Close();fs.Close();}}}}else{using (FileStream fs = new FileStream(logUrl, FileMode.CreateNew)){using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)){try{sw.Write(ex);}catch (Exception ex1){WriteLog(ex1);}finally{sw.Close();fs.Close();}}}}}//Select the wsp file action.private void select_wsp_button_Click(object sender, EventArgs e){OpenFileDialog wspFile = new OpenFileDialog();if (wspFile.ShowDialog() == DialogResult.OK) {WspText.Text = wspFile.FileName;}}//Retract and deploy action.private void ok_button_Click(object sender, EventArgs e){if (WebAppComBox.Text == "" || SiteComBox.Text == "" || UserNameText.Text == "" || PwdText.Text == "" || WspText.Text == "" || CAText.Text == ""){MessageBox.Show("You can not leave any box blank. Please check your input.");}else{//1.Login site and deactive the feature.IWebDriver iw = new InternetExplorerDriver();iw = login(iw, SiteComBox.Text.ToString(), UserNameText.Text.ToString(), PwdText.Text.ToString());INavigation navi = iw.Navigate();//Go to the site collection features page.navi.GoToUrl(SiteComBox.Text.ToString() + "/_layouts/15/ManageFeatures.aspx?Scope=Site");//Judge the feature category by the name wsp file selected.string category;var wspPath = WspText.Text.ToString().Split(new Char[] { '\\' });category = wspPath[wspPath.Count() - 1];//MessageBox.Show(category.ToString());//Deactive the feature. deactivateFeature(iw, category);//2.If has solution, retract first.string solutionPageUrl = CAText.Text + "/_admin/Solutions.aspx";navi.GoToUrl(solutionPageUrl);iw.FindElement(By.LinkText(category.ToLower())).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRetractSolution_LinkText");iw.FindElement(By.Id("ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRetractSolution_LinkText")).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_ctl02_RptControls_BtnSubmit");iw.FindElement(By.Id("ctl00_PlaceHolderMain_ctl02_RptControls_BtnSubmit")).Click();//During the retracting period, there will be a down. Let's sleep to get over it.//Thread.Sleep(300000);//Back to the wsp page. iw.FindElement(By.LinkText(category.ToLower())).Click();iw.Navigate().Refresh();iw.Close();}}//Deactive the feature accourding to the wsp solution category.private void deactivateFeature(IWebDriver iw,string category){if (category == "APPSSP2013MISite.wsp"){//Deactive the MISITE feature.waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_divFeatureStatus");string featureStatus = iw.FindElement(By.Id("ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_divFeatureStatus")).GetAttribute("featurestatus").ToString();if (featureStatus == "Active"){waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_btnActivate");iw.FindElement(By.Id("ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl21_ctl00_btnActivate")).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_lnkbtnDeactivate");iw.FindElement(By.Id("ctl00_PlaceHolderMain_lnkbtnDeactivate")).Click();}}//Other solutions can be extended here. }//Wait until page-element loaded method.private static void waitUntilPageLoaded(IWebDriver iw, string element){try{iw.FindElement(By.Id(element));}catch (Exception ex){WriteLog(ex);//Refresh the current page.//iw.Navigate().Refresh();Thread.Sleep(1000);waitUntilPageLoaded(iw, element);}}//Login SP site method.public static IWebDriver login(IWebDriver driver, string url,string userName,string pwd){INavigation navigation = driver.Navigate();navigation.GoToUrl(url);//driver.FindElement(By.Id("overridelink")).Click();IntPtr myPtr = GetForegroundWindow();//IntPtr hWnd = FindWindow(null, "abc");if (myPtr != IntPtr.Zero){//Send message to the window. System.Windows.Forms.SendKeys.SendWait(userName);System.Windows.Forms.SendKeys.SendWait("{TAB}");System.Windows.Forms.SendKeys.SendWait(pwd);System.Windows.Forms.SendKeys.SendWait("{ENTER}");}return driver;}//Remove the solution from the farm.private void remove_button_Click(object sender, EventArgs e){if (WspText.Text == "" || CAText.Text == ""){MessageBox.Show("You can not leave the 'WSP' and 'Central Admin' box blank.");}else{IWebDriver iw = new InternetExplorerDriver();INavigation navi = iw.Navigate();navi.GoToUrl(CAText.Text + "/_admin/Solutions.aspx");waitUntilPageLoaded(iw, "__gvctl00_PlaceHolderMain_GvItems__div");string category;var wspPath = WspText.Text.ToString().Split(new Char[] { '\\' });category = wspPath[wspPath.Count() - 1];iw.FindElement(By.LinkText(category.ToLower())).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRemoveSolution_LinkText");iw.FindElement(By.Id("ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkRemoveSolution_LinkText")).Click();//Click OK in the popup window.IntPtr myPtr = GetForegroundWindow();if (myPtr != IntPtr.Zero){System.Windows.Forms.SendKeys.SendWait("{ENTER}");}iw.Close();}}//Deploy the solution.private void deploy_button_Click(object sender, EventArgs e){if (WspText.Text == "" || CAText.Text == ""){MessageBox.Show("You can not leave the 'WSP' and 'Central Admin' box blank.");}else{//Open the PowerShell.SPSecurity.RunWithElevatedPrivileges(() =>{using (Runspace runspace = RunspaceFactory.CreateRunspace()){//MessageBox.Show("Run PowerShell."); runspace.Open();PowerShell ps = PowerShell.Create();ps.Runspace = runspace;Pipeline pipeline = runspace.CreatePipeline();pipeline.Commands.AddScript("Add-PSSnapin microsoft.sharepoint.powershell");string cmd = "Add-SPSolution " + WspText.Text.ToString();pipeline.Commands.AddScript(cmd);pipeline.Invoke();}});//Go to the solution-deploy page.IWebDriver iw = new InternetExplorerDriver();INavigation navi = iw.Navigate();navi.GoToUrl(CAText.Text + "/_admin/Solutions.aspx");waitUntilPageLoaded(iw, "__gvctl00_PlaceHolderMain_GvItems__div");string category;var wspPath = WspText.Text.ToString().Split(new Char[] { '\\' });category = wspPath[wspPath.Count() - 1];iw.FindElement(By.LinkText(category.ToLower())).Click();waitUntilPageLoaded(iw, "ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkDeploySolution_LinkText");iw.FindElement(By.Id("ctl00_PlaceHolderMain_solutionStatusToolBar_RptControls_LinkDeploySolution_LinkText")).Click();iw.FindElement(By.Id("ctl00_PlaceHolderMain_ctl02_RptControls_BtnSubmit")).Click();}}} } View Code至此,Deactivate Feature,Retract Solution,Remove Solution,Deploy Solution的過程就已經封裝好了。至于Active Feature由于界面大小有限就不寫了,和Deactivate Feature的過程是一樣的。
總結
以上是生活随笔為你收集整理的SharePoint自动化系列——Solution auto-redeploy using Selenium(C#)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: iOS:(接口适配器3)--iPhone
 - 下一篇: hpuoj--1093: 回文数(一)