2016-05-05 4 views
4

私は、ユーザーがファイルを開くためのソリューションを作成しています。このファイルは特定のWebサイトに移動し、ユーザーのユーザー名をログインフォームに挿入する必要があります。 このファイルには、Citrixセッションにアクセスしているユーザーがアクセスする必要があります。コンソールウィンドウや依存関係を持たない単純なDOM操作

これは非常に簡単であるべき、と私はPowerShellの経由でそれを行う方法を発見した:

$aduser = Get-ADUser $env:USERNAME -Properties EmailAddress 
$emailaddress = $aduser.EmailAddress 

$url = "https://website.org/loginpage.asp" 
$ie = New-Object -comobject "InternetExplorer.Application" 
$ie.visible = $true 
$ie.Navigate($url) 
WaitForPage 10 
$ie.Document.GetElementById("USERID").Value = $emailaddress 

これは完璧に動作します - それは、Webページを開き、ユーザー名(メールアドレス)を挿入します。

ただし、ユーザーがマシンからこれを実行すると、CMDウィンドウ(実行中の場合は.cmdまたは.bat)とPowershellウィンドウのどちらも非表示にすることはできないようです。 -WindowStyle Hiddenは、ウィンドウが表示される時間を短くしました。これは許容される解決策ではありません。

私の次の行動計画は、上記のコードをc#で作り直してexeとして配布することでした(これはコンソールウィンドウを表示しにくいためです)。しかし、C#で外部ライブラリに依存しない方法を見つけることはできません(Seleniumなど)。これは、ドライバをインストールする必要があります。これは、私にとって有効なオプションではありません。

私の質問は次のようなものです - 上記PowershellスクリプトはC#で再作成できますか?そのスクリプトの-comobjectは.NETオブジェクトですか、もしそうならC#でどのように活用できますか?


は、参考のために - (CMDファイルに)次のように私は現在.ps1ファイルを呼び出しています:

START Powershell.exe -WindowStyle Hidden -File \\file\Folder\SK\scripts\powershell\opensite.ps1 

そして、私は実際に表示されるコンソールウィンドウを隠すのいずれかの方法を発見していません。私はこれに対する解決法、またはC#で同じことを実装する簡単な方法を見つける必要があります。

+3

コードをvbscriptまたはjscriptに変換して、 'wscript.exe'で実行することができます。 Voila!コンソールウィンドウはありません。 – rojo

+1

@rojo powershell junkieとして、これは後ろ向きに見えますが、私はそれが簡単で、よくサポートされ、簡単だと認めなければなりません。私が考える答えの価値がある。 – briantist

答えて

1

I commented aboveとして、wscript.exeでVBScriptまたはJscriptを使用すると、別のコンソールウィンドウの起動を避けることができます。次に、バッチ+ Jscriptハイブリッドとして記述されたJscriptスクリプトの例を示します。 .bat拡張子を付けて保存し、味を塩にして、それを撃つ。

@if (@CodeSection == @Batch) @then 
@echo off & setlocal 

wscript /e:JScript "%~f0" 

goto :EOF 
@end // end batch/begin JScript hybrid code 

var user = WSH.CreateObject("ADSystemInfo"), 
    email = GetObject("LDAP://" + user.UserName).EmailAddress, 
    url = "https://website.org/loginpage.asp", 
    ie = WSH.CreateObject('InternetExplorer.Application'); 

ie.visible = true; 
ie.Navigate(url); 
while (ie.readyState != 4) WSH.Sleep(25); 

ie.document.getElementById('USERID').value = email; 

if (ie.document.getElementById('password')) 
    ie.document.getElementById('password').focus(); 

それはあなたがいずれかの拡張子.batまたは.jsファイルでそれを保存することができますように、実際にポリグロットスクリプトです。 .jsとしてダブルクリックすると起動します(デフォルトで.jsファイルがwscript.exeに関連付けられていると仮定します)。


.exeファイルを好む場合は、上記のスクリプトは、自己コンパイルしJscript.NET実行可能ファイルをリンクします一つにかなり容易に変更することができます。 (このスクリプトは、まだ拡張子.batを取得します。)私はきちんとロホの答えを理解するまで、私は以下のC#を使用していた

@if (@CodeSection == @Batch) @then 
@echo off & setlocal 

for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*jsc.exe"') do (
    if not exist "%~dpn0.exe" "%%~I" /nologo /target:winexe /out:"%~dpn0.exe" "%~f0" 
) 
"%~dpn0.exe" 
goto :EOF 
@end // end batch/begin JScript.NET hybrid code 

import System; 
import System.Diagnostics; 

try { 
    var wshShell:Object = new ActiveXObject("Wscript.Shell"), 
     user:Object = new ActiveXObject("ADSystemInfo"), 
     email:String = GetObject("LDAP://" + user.UserName).EmailAddress, 
     url:String = "https://website.org/loginpage.asp", 
     ie:Object = new ActiveXObject('InternetExplorer.Application'); 
} 
catch(e:Exception) { System.Environment.Exit(1); } 

ie.visible = true; 
ie.Navigate(url); 

// force IE window to the foreground and give it focus 
var proc:System.Diagnostics.Process[] = System.Diagnostics.Process.GetProcesses(); 
for (var i:Int16 = proc.length, hwnd:IntPtr = IntPtr(ie.hwnd); i--;) { 
    if (proc[i].MainWindowHandle === hwnd && wshShell.AppActivate(proc[i].Id)) break; 
} 

while (ie.readyState != 4) System.Threading.Thread.Sleep(25); 
ie.document.getElementById('USERID').value = email; 
if (ie.document.getElementById('password')) 
    ie.document.getElementById('password').focus(); 
+0

こんにちは、私は助けてくれてありがとう。残念ながら、これはまだ私がそれを使用することはできませんスクリプトを実行するときにコンソールウィンドウを表示します!私はもう一度解決策を見つけましたが、私はまもなくそれを発表します。 – Bassie

+1

@Bassie私はあなたが間違っていると思う。 .js拡張子を付けて保存した私の最初の解決策は、 'wscript'によって処理されるとコンソールウィンドウを表示しません。 「cscript」の「c」は* console *を表します。一方、「wscript」の「w」は、あなたが*間違っていることを意味します。 2番目の解決策では、生成されたthe.exeには 'target:winexe'スイッチごとにコンソールウィンドウも表示されません。また、それを作成する.batではなく、展開する.exeになります。 – rojo

+0

私はこれを見ています - 私はこれが私のデフォルトであると思ったので、 "wscriptを使って"実行していることを完全に理解していませんでしたが、私のデフォルトは 'cscript'に設定されているようです。 2番目のソリューションを再度実行した後、 '.exe'が生成されていることがわかります。このexe生成に関連する読書資料を教えてください。私はこれまでこれを見たことがないし、スタンドアロンのexesを作成する非常に便利な方法のように思える(私の現在の解決策は静的な場所に保存されたスクリプトを必要としているので確かにスタンドアロンではない) – Bassie

1

You can certainly call COM objects in C#, as explained in this existing answer

ライブラリがすでに登録されている場合は、Visual Studioがあなたのための相互運用機能アセンブリを生成する必要がありするには、次の の手順を実行することができます:Visual Studioプロジェクトにオープン

  • を。
  • 「参照」(ソリューションエクスプローラのプロジェクトのすぐ下)を右クリックし、「参照の追加」を選択します。
  • [COM]タブを選択します。
  • 相互運用するコンポーネントを選択します。
  • 「OK」を選択します。

これは、COM インターフェイスのすべてを通常のC#クラスでラップするクラスまたはC#クラスのセットです。次に、他のC#ライブラリ のように使用します。参照のインポートがうまくいけば、他の参照と同様に を調べて、 のメソッド/構造体/クラス/定数をその名前空間に表示し、 intellisenseにする必要があります。

また、RunspaceとPipelineを使用してC#内でPowerShellを実行することもできます。 See Runspace samples on MSDN(ここのリンクから例3'S):第二のアプローチは間違いなく長い時間がかかるとしていないされている間、あなたがそのように実行可能ファイルからPowerShellのコードを保持したい場合は

namespace Microsoft.Samples.PowerShell.Runspaces 
{ 
    using System; 
    using System.Collections; 
    using System.Management.Automation; 
    using System.Management.Automation.Runspaces; 
    using PowerShell = System.Management.Automation.PowerShell; 

    /// <summary> 
    /// This class contains the Main entry point for this host application. 
    /// </summary> 
    internal class Runspace03 
    { 
    /// <summary> 
    /// This sample shows how to use the PowerShell class to run a 
    /// script that retrieves process information for the list of 
    /// process names passed to the script. It shows how to pass input 
    /// objects to a script and how to retrieve error objects as well 
    /// as the output objects. 
    /// </summary> 
    /// <param name="args">Parameter not used.</param> 
    /// <remarks> 
    /// This sample demonstrates the following: 
    /// 1. Creating a PowerSHell object to run a script. 
    /// 2. Adding a script to the pipeline of the PowerShell object. 
    /// 3. Passing input objects to the script from the calling program. 
    /// 4. Running the script synchronously. 
    /// 5. Using PSObject objects to extract and display properties from 
    /// the objects returned by the script. 
    /// 6. Retrieving and displaying error records that were generated 
    /// when the script was run. 
    /// </remarks> 
    private static void Main(string[] args) 
    { 
     // Define a list of processes to look for. 
     string[] processNames = new string[] 
     { 
     "lsass", "nosuchprocess", "services", "nosuchprocess2" 
     }; 

     // The script to run to get these processes. Input passed 
     // to the script will be available in the $input variable. 
     string script = "$input | get-process -name {$_}"; 

     // Create a PowerShell object. Creating this object takes care of 
     // building all of the other data structures needed to run the script. 
     using (PowerShell powershell = PowerShell.Create()) 
     { 
     powershell.AddScript(script); 

     Console.WriteLine("Process    HandleCount"); 
     Console.WriteLine("--------------------------------"); 

     // Invoke the script synchronously and display the 
     // ProcessName and HandleCount properties of the 
     // objects that are returned. 
     foreach (PSObject result in powershell.Invoke(processNames)) 
     { 
      Console.WriteLine(
          "{0,-20} {1}", 
          result.Members["ProcessName"].Value, 
          result.Members["HandleCount"].Value); 
     } 

     // Process any error records that were generated while running 
     // the script. 
     Console.WriteLine("\nThe following non-terminating errors occurred:\n"); 
     PSDataCollection<ErrorRecord> errors = powershell.Streams.Error; 
     if (errors != null && errors.Count > 0) 
     { 
      foreach (ErrorRecord err in errors) 
      { 
      System.Console.WriteLine(" error: {0}", err.ToString()); 
      } 
     } 
     } 

     System.Console.WriteLine("\nHit any key to exit..."); 
     System.Console.ReadKey(); 
    } 
    } 
} 

は、それが意味をなすこと毎回再コンパイルすることなく、より簡単に変更することができます。

exeは、特定のPowerShellスクリプトを目に見えない形で実行するために使用することができます。

+0

有益な答えをありがとう。 PowerShellスクリプトで使用した 'COM'オブジェクトが何であるか知っていますか? PowerShellでは、 'InternetExplorer.Application'と呼ばれるようですが、Visual Studioの' COM'リファレンスタブでこれを検索すると見つけることができません - 私が得ることのできるものは 'Microsoft Internet Controls'です右。もう一度お返事します – Bassie

+1

@Bassie私は知らないのでしょうか? [このページのコードプロジェクト](http://www.codeproject.com/Articles/9683/Automating-Internet-Explorer)は、「Microsoft Internet Controls」が必要とする参考資料の1つであることを示唆しているようですが、私はあなたが期待したよりも多くの仕事をしてください。 [この質問への回答](http://stackoverflow.com/q/8438782/3905079)では、第三者のライブラリを使用することが推奨されています。また、あなたの質問にrojoのコメントを見てください。 'wscript.exe'が既にOSに含まれているので、これはかなり良い選択です。 – briantist

0

。このメソッドはうまくいきますが、rojoのようにシンプルでエレガントではありませんので、答えとしてマークしました。

static class Program 
{ 
    private static void Main() 
    { 
     var startInfo = new ProcessStartInfo(@"\\file\administration\Unused\Apps\opencascade\Alternate.bat") 
     { 
      WindowStyle = ProcessWindowStyle.Hidden, 
      UseShellExecute = false, 
      CreateNoWindow = true 
     }; 
     Process.Start(startInfo); 

     var startInfo = new ProcessStartInfo("Wscript.exe", @"\\file\administration\Unused\Apps\opencascade\Alternate.js") 
     { 
      WindowStyle = ProcessWindowStyle.Hidden, 
      UseShellExecute = false, 
      CreateNoWindow = true 
     }; 
     Process.Start(startInfo); 

     var startInfo = new ProcessStartInfo("Powershell.exe", 
      @"\\file\administration\Unused\Apps\opencascade\opencascade.ps1") 
     { 
      WindowStyle = ProcessWindowStyle.Hidden, 
      UseShellExecute = false, 
      CreateNoWindow = true 
     }; 
     Process.Start(startInfo); 
    } 
} 

ここでの主な方法は、3つの異なるソリューションを1つずつ実行することです。異なる「バージョン」は、それぞれ環境内で.batまたは.ps1または.jsを使用する方が意味があるかどうかによって異なります。この文脈で動作する.jsバージョンを使用し、このC#コードによって生成された実行可能ファイルは結果のコンソールウィンドウを隠します。

関連する問題