How to run Azure cmdlets from a powershell script in a published Web Role VS2012 project

别来无恙 提交于 2019-12-11 13:42:25

问题


I have a VS 2012 MVC 4 web role project and I successfully call a powershell script from the bin directory of the role, after I run Set-ExecutionPolicy Unrestricted from a startup cmd. The script contains some azure cmdlets and when I run the project locally the script works perfectly. However when I publish the project on Azure, the same azure cmdlets in the script do not run. For example:

param([string]$websiteName="itudkcloudqwerdfs", [string]$serverLogin="user", [string]$serverPass="paSS123!@#", [string]$location="North Europe")

# Create new Website
#

$website = New-AzureWebsite -Location $location -Name $websiteName

if ($website -eq $null)
{
    throw "Website creation error"
    exit
}

creates an Azure website successfully when run locally but throws and exits when published and run from the cloud service.

Of course I googled around for a solution and I found that I have to pre-install Azure Powershell to the Web Role in order to run Azure cmdlets there. To do that, I installed the web platform installer 4.5, copied its command line tool executable with the Microsoft.Web.PlatformInstaller dll and my Azure publishsettings file to my Web Role's bin folder and I created a cmd that installs the Azure Powershell from webpicmd to a special folder in the Web Role's bin directory and imports my publishsettings file on Web Role startup:

md "%~dp0appdata"
cd "%~dp0appdata"
cd..

reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d "%~dp0appdata" /f

"%~dp0\WebpiCmd.exe" /Install /AcceptEula /Products:WindowsAzurePowershell /log:%~dp0WindowsAzurePowershell.log

reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f

powershell Import-AzurePublishSettingsFile
exit /b 0

It still didn't work, so I remotely logged in to the instance to see for myself what could be wrong. I tried to run the cmd script above and it required the .NET Framework 3.5 feature enabled, which looks weird to me since the instance already has the .NET 4.5 feature enabled by default (Windows Server 2012). Anyway, I enabled it from the server manager and the script ran successfully with no errors. I opened the powershell and I tested some Azure cmdlets and they worked. However, even after that, when I invoke the script again from the web app, it still doesn't run the azure cmdlets and exits.

What am I missing? And why does webpicmd requires the .NET 3.5 feature? Is there an alternative solution to this?

Update: After Gaurav's comment, I added this into my servicedefinition.csdef under the WebRole tag to run the webrole in an elevated execution context but the azure cmdlets are still not running in the script:

<Runtime executionContext="elevated" />

Update: Here's the C# code that invokes the script

//create command
string path = HttpContext.Server.MapPath("/bin/InitializeResources.ps1");
PSCommand cmd = new PSCommand();

cmd.AddCommand(path);
cmd.AddParameter("websiteName", websiteName);
cmd.AddParameter("serverLogin", username);
cmd.AddParameter("serverPass", password);
cmd.AddParameter("location", location);

//set the command into a powershell object and invoke it
Runspace runspace = RunspaceFactory.CreateRunspace();
PowerShell ps = PowerShell.Create();
ps.Commands = cmd;

try
{
    runspace.Open();
    RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
    runSpaceInvoker.Invoke("Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force");
    ps.Runspace = runspace;

    Collection<PSObject> commandResults = ps.Invoke();

    //save results
    WebsiteInfo websiteInfo = new WebsiteInfo();
    foreach (PSObject result in commandResults)
    {
        websiteInfo.Connectionstring = (string)result.Members["ConnectionString"].Value;
        websiteInfo.WebsiteURL = (string)result.Members["WebsiteUrl"].Value;
        websiteInfo.ftpUrl = (string)result.Members["SelfLink"].Value;
        websiteInfo.ftpUrl = websiteInfo.ftpUrl.Substring(8);
        int index = websiteInfo.ftpUrl.IndexOf(":");
        if (index > 0)
            websiteInfo.ftpUrl = websiteInfo.ftpUrl.Substring(0, index);
        websiteInfo.ftpUrl = websiteInfo.ftpUrl.Replace("api", "ftp");
        websiteInfo.publishUsername = (string)result.Members["Repository"].Value + "\\" + (string)result.Members["PublishUsername"].Value;
        websiteInfo.publishPassword = (string)result.Members["PublishPassword"].Value;
    }

    runspace.Dispose();
    runspace = null;
    ps.Dispose();
    ps = null;
}

回答1:


I'm facing a similar problem as you can see in this thread I couldn't see any exception in Event Viewer as you, but adding these lines after each shell invoke I could see that my errors comes in the Import-Module line.

if (shell1.Streams.Error.Count > 0)
{
   for (int i = 0; i < shell1.Streams.Error.Count; i++)
   {
       ResultBox.Text += "Error: " + shell1.Streams.Error[i] + "\r\n";
   }
}



回答2:


At the time when we did that project with almamouz, it was not possible to generate resources via Azure REST API nor it was possible to do that via powershell scripts from webrole due to security considerations. We ended up using web and worker roles and the powershell script was running in worker role. It contained all the sensitive server connection info.



来源:https://stackoverflow.com/questions/16196184/how-to-run-azure-cmdlets-from-a-powershell-script-in-a-published-web-role-vs2012

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!