2015-03-02 87 views
0

我正在使用Azure文件服务来保存某个程序安装在角色实例上的文件可以访问的文件。使用PowerShell安装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文件 - wit h相同的参数 - 在工作角色的远程桌面中,将挂载映射的驱动器并安装程序。但是在部署之后(即从OnStart())调用代码中的相同文件不会安装驱动器。 ProgramAuthor.ProgramFile.exe被执行,并尝试在映射的驱动器中安装,但从未映射,因此失败。

这是怎么回事?

回答

0

好的,所以我去掉了this way而不是this answer。唯一的问题是当登录到虚拟机时驱动器不会显示在文件资源管理器中。没什么大不了的。

+0

我将运行时executioncontext更改为提升,因此驱动器显示在文件资源管理器中,但标有红色十字,并表示它不可访问,因为用户名或密码不正确。带有安装文件的程序仍在运行! – 2015-03-03 08:16:13

相关问题