使用powershell挂载Azure文件服务映射驱动器

时间:2015-03-02 13:20:18

标签: powershell azure-worker-roles

我正在使用Azure文件服务来保存安装在角色实例上的程序可以访问的某些文件。

我已设法使用PowerShell脚本通过远程桌面将驱动器映射到文件服务共享。但是,当我尝试执行相同的脚本时,在辅助角色的OnStart()中,它不起作用。我无法弄清楚出了什么问题。

所以,这就是我的工作:

public override bool OnStart()
{
    ServicePointManager.DefaultConnectionLimit = 12;

    _slsPath = RoleEnvironment.GetLocalResource("StartupLocalStorage").RootPath;

    var settingstring = CloudConfigurationManager.GetSetting("StorageConnectionString");
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(settingstring);

    var blobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container = blobClient.GetContainerReference("zipfiles");
    ICloudBlob blob = container.GetBlobReferenceFromServer("Program.zip");
     //copy blob from cloud to local gallery
     blob.DownloadToFile(_slsPath + "Program.zip", FileMode.Create);

    // get powershell script for mounting drive
     blob = container.GetBlobReferenceFromServer("mountdrive.ps1");
    blob.DownloadToFile(_slsPath + "mountdrive.ps1", FileMode.Create);

    // small exe for executing powershell script for mounting drive
    blob = container.GetBlobReferenceFromServer("Programinstaller.exe");
    blob.DownloadToFile(_slsPath + "Programinstaller.exe", FileMode.Create);

    ZipFile.ExtractToDirectory(_slsPath + @"\Program.zip", _slsPath);

    var share = storageAccount
    .CreateCloudFileClient()
    .GetShareReference("someshare");
    share.CreateIfNotExists();

    var filesPath = @"Z:\Folder";
    // Mounting drive
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = false;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardOutput = true;
    startInfo.FileName = _slsPath + @"Programinstaller.exe";
    startInfo.WindowStyle = ProcessWindowStyle.Normal;
    startInfo.Arguments = _slsPath + @"\ " + filesPath;

    // Start the process with the info we specified.
    // Call WaitForExit and then the using statement will close.
    using (Process exeProcess = Process.Start(startInfo))
    {
            int count = 0;
            var res = exeProcess.StandardOutput.ReadLine();
            System.IO.File.WriteAllText(_slsPath + @"ResultOfDriveMount.txt", res + Environment.NewLine);
            while (count < 30)
            {
                    Thread.Sleep(1000);
                    res = exeProcess.StandardOutput.ReadLine();
                    System.IO.File.AppendAllText(_slsPath + @"ResultOfDriveMount.txt", res + Environment.NewLine);
                    count++;
            }
    }
}

好的,所以,Programinstaller.exe就是这样:

    static void Main(string[] args)
    {
        Console.WriteLine(args[0]);
        Thread t = new Thread(() =>
        {
            ExecutePowerShell(args[0] + "mountdrive.ps1", args[0]);
        });
        t.Start();
        Thread.Sleep(20000);
        InstallProgram(args[0], args[1]);
    }

    private static void ExecutePowerShell(string scriptfile, string SlsPath)
    {
        RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

        Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
        runspace.Open();

        RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);

        Pipeline pipeline = runspace.CreatePipeline();

        //Here's how you add a new script with arguments
        Command myCommand = new Command(scriptfile);
        //CommandParameter testParam = new CommandParameter("key", "value");
        //myCommand.Parameters.Add(testParam);

        pipeline.Commands.Add(myCommand);

        // Execute PowerShell script
        var results = pipeline.Invoke();
        foreach (var res in results)
            System.IO.File.WriteAllText(SlsPath + @"ResultOfPowerShell.txt", res.ToString());
    }

    /// <summary>
    /// Launch the legacy application with some options set.
    /// </summary>
    static void InstallProgram(string folderPath, string pathTwo)
    {
        // Use ProcessStartInfo class
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.CreateNoWindow = false;
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.FileName = folderPath + @"ProgramAuthor.ProgramName.exe";
        startInfo.WindowStyle = ProcessWindowStyle.Normal;
        startInfo.Arguments = folderPath + [someargument] + pathTwo;

        try
        {
            // Start the process with the info we specified.
            // Read output lines, store to txt
            using (Process exeProcess = Process.Start(startInfo))
            {
                int count = 0;
                var result = exeProcess.StandardOutput.ReadLine(); 

                System.IO.File.WriteAllText(folderPath + @"ResultOfProgramInstall.txt", result + Environment.NewLine);
                while (count < 300)
                {
                    Thread.Sleep(1000);
                    result = exeProcess.StandardOutput.ReadLine();
                    System.IO.File.AppendAllText(folderPath + @"ResultOfProgramInstall.txt", result + Environment.NewLine);
                    count++;
                }
            }
        }
        catch (Exception ex)
        {
            System.IO.File.WriteAllText(folderPath + @"Error2.txt", ex.Message + " ... " + ex.StackTrace);
        }
    }

Ps1文件是这样的:

Set-Executionpolicy -Scope CurrentUser -ExecutionPolicy UnRestricted
cmdkey /add:[account].file.core.windows.net /user:[account] /pass:[key]
net use z: \\[account].file.core.windows.net\someshare

奇怪的是,运行从blob下载的Programinstaller.exe文件,从命令提示符 - 使用相同的参数 - 在worker角色的远程桌面中,将挂载映射的驱动器并安装程序。但是在部署之后从代码调用相同的文件(即从OnStart())不会安装驱动器。执行ProgramAuthor.ProgramFile.exe,并尝试在映射的驱动器中安装,但它从未映射,因此失败。

这是怎么回事?

1 个答案:

答案 0 :(得分:0)

好的,所以我按照this way中的建议改为this answer。唯一的问题是登录到VM时驱动器未显示在文件资源管理器中。没什么大不了的。