Заказчик отказывается от «скриптов» в среде.Как мне вставить * .ps1 в приложение C #? - PullRequest
4 голосов
/ 11 февраля 2012

У меня есть следующий пример скрипта Powershell, который встроен в мое приложение C #.

Код 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 предлагает следующие варианты встраивания:

enter image description here

Каждый образец PowerShellЯ видел (MSDN на Exchange , а MSFT Dev Center ) требовал, чтобы я разбил команду Powershell на "биты" и отправил ее через анализатор.

Я не хочу оставлять много файлов PS1 с моим приложением, мне нужно иметь один двоичный файл без другого «поддерживающего» файла PS1.

Как я могу сделать так, чтобы myapp.exe был единственнымчто видит мой клиент?

Ответы [ 6 ]

5 голосов
/ 11 февраля 2012

Многие клиенты не хотят уходить от политики ограниченного исполнения, потому что они на самом деле ее не понимают.Это не граница безопасности - это просто дополнительный обруч, через который можно прыгнуть, чтобы не выстрелить себе в ногу.Если вы хотите запускать сценарии 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");

Используя нулевой менеджер авторизации, политику выполнениязавершено игнорируется.Помните - это не какой-то «взлом», потому что политика выполнения защищает пользователей от самих себя.Это не для защиты от злонамеренных третьих лиц.

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

3 голосов
/ 11 февраля 2012

Прежде всего вы должны попытаться удалить отвращение вашего клиента к сценариям.Читайте о подписании скрипта, политике выполнения и т. Д.

Сказав это, вы можете иметь скрипт в виде многострочной строки в самом коде C # и выполнять его. Поскольку у вас есть только один простой скрипт, это самый простой подход.

Вы можете использовать AddScript, ethos, который принимает скрипт как строку (не путь к скрипту)

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

1 голос
/ 11 февраля 2012

Сохраните ваши 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;
    }
  }
}
1 голос
/ 11 февраля 2012

Вы как бы зависали от ответа сами.Добавив его как контент, вы можете получить к нему доступ во время выполнения (см. Application.GetResourceStream).Затем вы можете либо сохранить его как временный файл и выполнить, либо найти способ вызвать powershell без использования файлов.

1 голос
/ 11 февраля 2012

Вы можете встроить его в качестве ресурса и получить его путем отражения во время выполнения.Вот ссылка с MSDN .Статья восстанавливает встроенные изображения, но принцип тот же.

0 голосов
/ 11 февраля 2012

Заказчик просто не видит сценарий PowerShell в том, что вы развертываете, верно? Вы можете делать все, что вы хотите во время выполнения. Так что запишите его во временный каталог - даже попробуйте именованный канал, если вы хотите получить модные и избегать файлов - и просто запустите на этом процесс PowerShell.

Вы можете даже попробовать передать его напрямую в stdin. Наверное, это то, что я бы попробовал первым. Тогда у вас нет никаких записей о том, что это где-то на компьютере. Класс Process достаточно универсален, чтобы делать подобные вещи, не касаясь Windows API напрямую.

...