4

C# アプリケーションに埋め込まれた次のサンプル Powershell スクリプトがあります。

Powershell コード

    $MeasureProps = "AssociatedItemCount", "ItemCount", "TotalItemSize"

   $Databases = Get-MailboxDatabase -Status
    foreach($Database in $Databases) {

        $AllMBStats = Get-MailboxStatistics -Database $Database.Name    
     $MBItemAssocCount = $AllMBStats   |   %{$_.AssociatedItemCount.value} |  Measure-Object -Average   -Sum
     $MBItemCount =      $AllMBStats   |   %{$_.ItemCount.value} |  Measure-Object -Average  -Sum

        New-Object PSObject -Property @{
            Server = $Database.Server.Name
            DatabaseName = $Database.Name
            ItemCount = $MBItemCount.Sum
        }
    }

Visual Studio には、次の埋め込みオプションがあります。

ここに画像の説明を入力

私が見たすべての PowerShell サンプル (MSDN on Exchangeおよび MSFT Dev Center ) では、Powershell コマンドを「ビット」に分割し、パーサーを介して送信する必要がありました。

アプリケーションに多くの PS1 ファイルを残したくありません。「サポートする」PS1 ファイルが他にない単一のバイナリが必要です。

myapp.exe だけが顧客に表示されるようにするにはどうすればよいですか?

4

6 に答える 6

6

多くのお客様は、制限された実行ポリシーをよく理解していないため、制限された実行ポリシーから離れることをためらっています。これはセキュリティの境界ではありません。自分の足を撃たないように飛び越えるための追加の輪です。独自のアプリケーションで ps1 スクリプトを実行する場合は、単純に独自の実行空間を使用し、システム実行ポリシーに注意を払わない基本承認マネージャーを使用します。

InitialSessionState initial = InitialSessionState.CreateDefault();

// Replace PSAuthorizationManager with a null manager which ignores execution policy
initial.AuthorizationManager = new
      System.Management.Automation.AuthorizationManager("MyShellId");

// Extract psm1 from resource, save locally
// ...

// load my extracted module with my commands
initial.ImportPSModule(new[] { <path_to_psm1> });

// open runspace
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();

RunspaceInvoke invoker = new RunspaceInvoke(runspace);

// execute a command from my module
Collection<PSObject> results = invoker.Invoke("my-command");

// or run a ps1 script    
Collection<PSObject> results = invoker.Invoke("c:\temp\extracted\my.ps1");

null 承認マネージャーを使用することで、実行ポリシーは完全に無視されます。実行ポリシーはユーザーを自分自身から保護するためのものであるため、これは「ハック」ではないことに注意してください。悪意のある第三者から保護するためのものではありません。

http://www.nivot.org/nivot2/post/2012/02/10/Bypassing-Restricted-Execution-Policy-in-Code-or-in-Script.aspx

于 2012-02-11T04:14:18.763 に答える
3

まず最初に、顧客の嫌悪感をスクリプトから削除してみてください。スクリプトの署名、実行ポリシーなどについて読んでください。

そうは言っても、C#コード自体に複数行の文字列としてスクリプトを記述して実行することができます。単純なスクリプトが1つしかないため、これが最も簡単な方法です。

スクリプトを文字列(スクリプトパスではなく)として受け取るAddScript、ethosを使用できます

http://msdn.microsoft.com/en-us/library/dd182436(v=vs.85).aspx

于 2012-02-11T02:32:07.943 に答える
1

これをリソースとして埋め込み、実行時にリフレクションを介して取得できます。こちらがMSDNからのリンクです。この記事では埋め込み画像を取得していますが、原則は同じです。

于 2012-02-11T02:30:44.300 に答える
1

あなたは自分で答えをホバリングしました。コンテンツとして追加することで、実行時にアクセスできます(Application.GetResourceStreamを参照)。次に、それを一時ファイルとして保存して実行するか、ファイルを使用せずにPowerShellを呼び出す方法を見つけます。

于 2012-02-11T02:30:52.173 に答える
1

POSH スクリプトを埋め込みリソースとして保存し、必要に応じて、この MSDN スレッドのコードのようなものを使用して実行します。

public static Collection<PSObject> RunScript(string strScript)
{
  HttpContext.Current.Session["ScriptError"] = "";
  System.Uri serverUri = new Uri(String.Format("http://exchangsserver.contoso.com/powershell?serializationLevel=Full"));
  RunspaceConfiguration rc = RunspaceConfiguration.Create();
  WSManConnectionInfo wsManInfo = new WSManConnectionInfo(serverUri, SHELL_URI, (PSCredential)null);
  using (Runspace runSpace = RunspaceFactory.CreateRunspace(wsManInfo))
  {
    runSpace.Open();
    RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
        scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
    PowerShell posh = PowerShell.Create();
    posh.Runspace = runSpace;
    posh.AddScript(strScript);
    Collection<PSObject> results = posh.Invoke();
    if (posh.Streams.Error.Count > 0)
    {
      bool blTesting = false;
      string strType = HttpContext.Current.Session["Type"].ToString();
      ErrorRecord err = posh.Streams.Error[0];
      if (err.CategoryInfo.Reason == "ManagementObjectNotFoundException")
      {
    HttpContext.Current.Session["ScriptError"] = "Management Object Not Found Exception Error " + err + " running command " + strScript;
    runSpace.Close();
    return null;
      }
      else if (err.Exception.Message.ToString().ToLower().Contains("is of type usermailbox.") && (strType.ToLower() == "mailbox"))
      {
    HttpContext.Current.Session["ScriptError"] = "Mailbox already exists.";
    runSpace.Close();
    return null;
      }
      else
      {
    HttpContext.Current.Session["ScriptError"] = "Error " + err + "<br />Running command " + strScript;
    fnWriteLog(HttpContext.Current.Session["ScriptError"].ToString(), "error", strType, blTesting);
    runSpace.Close();
    return null;
      }
    }
    runSpace.Close();
    runSpace.Dispose();
    posh.Dispose();
    posh = null;
    rc = null;
    if (results.Count != 0)
    {
      return results;
    }
    else
    {
      return null;
    }
  }
}
于 2012-02-11T02:35:43.520 に答える
0

顧客は、デプロイしたものに PowerShell スクリプトが表示されないだけですよね? 実行時に必要なことは何でもできます。したがって、それを一時ディレクトリに書き込みます。ファイルを避けたい場合は、名前付きパイプを試してください。そして、その上で PowerShell プロセスを開始するだけです。

標準入力に直接パイプすることもできます。それはおそらく私が実際に最初に試したことです。次に、コンピューターのどこかにあるという記録はありません。Process クラスは、Windows API に直接触れることなく、そのようなことを行うのに十分な汎用性を備えています。

于 2012-02-11T04:10:50.877 に答える