アプリ版:「スタンプのみでお礼する」機能のリリースについて

OSはwin8.1 64bitです。

VBフォームアプリケーション上に設置したコマンドボタンを押すだけで
コマンドプロンプトからwindowsエクスペリエンスインデックスを実行したいと考えているのですが、
Windowsから直接立ち上げたコマンドプロンプトに「winsat formal -restart clean」と
入力すると問題なく始まるものの、
VBフォームから実行すると、「'winsat' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません」とエラーが出ます。

Dim ShellObj
ShellObj = CreateObject("WScript.Shell")
Call ShellObj.Run("cmd.exe /k winsat formal -restart clean")

Windowsから直接立ち上げる際、管理者権限を使用しなくても
問題なく走るため、管理者権限は関係ないと考えて良いのでしょうか?

また、どういった記述であればWindowsエクスペリエンスが実行できるでしょうか?
出来ればバッチやスクリプトは使用したくありません。

よろしくお願いいたします。

質問者からの補足コメント

  • うーん・・・

    ひとつ気付いたことがあるため、補足いたします。

    VB上から何も引数を指定していないまっさらなコマンドプロンプト(c:\)を開き、
    winsat formal -restart cleanを実行したところ、同様のエラーが発生しました。

    つまり、Windowsから直接起動したコマンドプロンプトと
    VBから起動したコマンドプロンプトとでは、
    実行できるコマンドが異なるということです。

    [ipconfig]や[netstat -ano]や[ping]などは通りました。
    ghost305jpさんからのご回答を受け、
    スペースを含む引数にはダブルクォーテーション2つで囲う
    という部分が原因かと考えておりましたが、どうやら根本的に
    何か別の原因があるようです。

      補足日時:2016/05/07 22:27

A 回答 (7件)

ユーザー名を指定しないと、なぜかDirで出て来ませんでした。


(少し調べれば、分かるかもしれませんが・・・)
以下で、起動しました。環境は、VB2008でやってみました。
テストしながらしてるので、注釈が入っております。



Dim strUserName As String = "UserName"'Windowsのユーザー名
Dim strPassText As String = "Password" 'パスワード
Dim prss1 As New System.Diagnostics.Process
Dim secStr As New System.Security.SecureString
For Each c As Char In strPassText
secStr.AppendChar(c)
Next

With prss1
With .StartInfo
'出力を読み取れるようにする
.UseShellExecute = False
'.RedirectStandardOutput = True
'.RedirectStandardInput = False
'ウィンドウを表示しないようにする
.CreateNoWindow = False 'True:非表示

.UserName = strUserName
.Password = secStr

''UACダイアログが親プログラムに対して表示されるようにする()
'.ErrorDialog = True
'.ErrorDialogParentHandle = Me.Handle

'作業フォルダを指定する
.WorkingDirectory = "C:\WINDOWS\System32"

'.Verb = "runas" '管理者実行
.FileName = "cmd.exe"
'.Arguments = """/K Dir C:\WINDOWS\System32\winsat*"""
.Arguments = "/K WinSAT.exe formal -restart clean"

End With

.Start()


'終了するまで待つ
.WaitForExit()

.Close()

End With
    • good
    • 1
この回答へのお礼

おおっ! 見事に走りました!
なぜユーザー名を指定しなければ弾かれるのかサッパリですが、
不可能と思われていたことが実現してプログラムの楽しさや奥深さを再確認しました。

ghost305jp様とのやり取りの中、学ぶことがたくさんあって
今まで知りたかった「外部プログラムの管理者権限による起動」や、
「個人フォルダを含むディレクトリの指定」、「バッチファイルの書き出し」など、
大変、有用な情報を提供していただき、本当にありがとうございました。
何の見返りもない中で最後までお付き合いくださったことも、重ねてお礼申し上げます。

実際、ユーザー名とパスワードを指定するという方法は
ユーザー名ならばEnvironment.UserNameで自動取得できるものの、
パスワードは自動取得など当然できない上に、
Nullという状態がローカルポリシーを設定しないかぎり認められず、
どちらにしても使用者に手間を与えてしまうため、現実的とは言えません。

今後はこの記述を基に、より簡素な操作で完結するプログラムを打ち込みたいと思います。

お礼日時:2016/05/09 22:38

No4について


①フォームからのボタン処理で行っていなければ、そのエラーになると思います。

No5について
別ファイルで配布ではなく、VBから環境に合わせて作れば良いと思います。
①AppDataフォルダ(下参照)の下位に、ファイルを作成します。
 System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
②ファイルの保存方法は、System.IO.StreamWriter を検索して見てください。
③作成したファイルを実行します。
    • good
    • 0
この回答へのお礼

日を跨いでまでご回答くださってありがとうございます。
アドバイスいただいたように、バッチファイルを書き出して
実行したのですが、なぜか最初と同じく、
「内部コマンドまたは外部コマンド・・・」のエラーが。

また、ご教示いただいた個人ファイルパスのコードについて、
これは有り難い! と、組み込もうと模索したのですが、
初心者につき理解に及ばず、
とりあえず下記のように短絡的なコードで実行しました。

Dim psi As New System.Diagnostics.ProcessStartInfo()
System.IO.Directory.CreateDirectory("C:\WindowsExperienceIndex")
Dim sw As New System.IO.StreamWriter("C:\WindowsExperienceIndex\WEI.bat")
sw.Write("WinSAT formal -restart clean")
sw.Close()
Dim p As System.Diagnostics.Process =
System.Diagnostics.Process.Start("c:\WindowsExperienceIndex\WEI.bat")
p.WaitForExit()

.batの書き出しも実行も上手くいっているのですが、
なぜかVB越しに実行するとことごとく弾かれます。

もう本当に八方ふさがりです。

お礼日時:2016/05/08 23:53

私は、winsatの存在自体知りませんでした。



ちなみに
コマンドで実行した時に表示されているログを参照したいのであれば、
やはり、バッチをお勧めしますが・・
①バッチファイルを2つ作成
【RUN_Winsat1.bat】
1行目:RUN_Winsat2.bat > RUN_Winsat2.log

【RUN_Winsat2.bat】
1行目:winsat formal -restart clean

②RUN_Winsat1.batを起動
③RUN_Winsat2.logを解析表示
    • good
    • 0
この回答へのお礼

winsatはwin7以降のOSでシステム欄からエクスペリエンスが消えていたため、調べるに至りました。
職業柄、顧客からハード性能の評価を知りたいとの声が多いため、今回のプログラムが必要になりました。

ご指示があったバッチファイルを作成して実行しましたところ、
Logファイルには下記の一行のみが綴られていました。

C:\Users\個人用フォルダ名\Documents>winsat formal -restart clean

実行中、パスなど注視していましたが、特に変わった点は見つけられませんでした。

ひとつ提案ですが、
バッチファイルをVBフォームに埋め込むことは可能なのでしょうか?
どうしても別ファイルにして配布するということは避けたいのです。

お礼日時:2016/05/08 02:14

動いているか分からないから、管理者権限で実行




Dim psi As New System.Diagnostics.ProcessStartInfo()

'ShellExecuteを使う。デフォルトtrueなので、必要はない。
psi.UseShellExecute = True
'起動するファイルのパスを指定する
psi.FileName = "cmd.exe"
'動詞に「runas」をつける
psi.Verb = "runas"
'コマンドライン引数を指定する
psi.Arguments = """-k WinSAT formal -restart clean"""

'作業フォルダを指定する
psi.WorkingDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.System)

'UACダイアログが親プログラムに対して表示されるようにする()
psi.ErrorDialog = True
psi.ErrorDialogParentHandle = ParentForm.Handle


Try
'起動する
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
'終了するまで待つ
p.WaitForExit()
Catch generatedExceptionName As System.ComponentModel.Win32Exception
'「ユーザーアカウント制御」ダイアログでキャンセルされたなどによって
'起動できなかった時
End Try
    • good
    • 0
この回答へのお礼

早くも次のご回答が。ありがとうございます。

実行しましたところ、
psi.ErrorDialogParentHandle = ParentForm.Handle  ←ここで下記のエラーが発生しました。

型 'System.NullReferenceException' のハンドルされていない例外が WinTools.exe で発生しました
追加情報:オブジェクト参照がオブジェクト インスタンスに設定されていません。

また、psi.ErrorDialogParentHandle = ParentForm.Handle の部分を抜いて実行したところ、
管理者権限の確認画面を通過し、先ほどの状況と変わらず待機状態になりました。
管理者権限や処理のタイミングでもないとなると、かなり難題です。

個人的に色々調べているのですが、
どうもWinSAT formal -restart cleanをVBから実行したという事例が見つけられず
八方ふさがりとなっています。

お礼日時:2016/05/08 01:45

終了するまで待つを加えて




Dim p As System.Diagnostics.Process
Dim psi As New System.Diagnostics.ProcessStartInfo()
'起動するファイルのパスを指定する
psi.FileName = "cmd.exe"
'コマンドライン引数を指定する
psi.Arguments = """-k WinSAT formal -restart clean"""

'作業フォルダを指定する
psi.WorkingDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.System)


'アプリケーションを起動する
p = System.Diagnostics.Process.Start(psi)

'終了するまで待つ
p.WaitForExit()
    • good
    • 0
この回答へのお礼

夜分遅くにご回答くださって本当にありがとうございます。
そしてプログラムの方も重ね重ね感謝いたします。
残念ながら成功には至りませんでしたが、結果に少し変化がありました。
エラーが無くなったことと、ディレクトリがC:\Windows\Sytem32>に変わったことです。

C:\Windows\Sytem32>   ←この状態のまま処理が終わっている。

また、カーソルの自由が効いたため、エクスペリエンスの実行コマンドを手動で打ってみたところ、
やはりVBから立ち上げたコマンドプロンプトのせいか、同じエラーが出て走りませんでした。

処理が終わっていると書きましたが、実はいただいたプログラムの下に
MsgBoxを置いて終了したかどうか確認してみましたところ、コマンドプロンプトを落としてから
メッセージが表示されました。

余談ですが、終了まで待機するプログラムは非常に助かります。
エクスペリエンス評価後にPowerShellを用いて結果を表示するプログラムを用意しているため、
意図しないところでプログラムが進化し、大変喜ばしく思っております。

お礼日時:2016/05/08 01:27

No1の追記で


以下を追加したらどうなりますか?

'作業フォルダを指定する
psi.WorkingDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.System)
    • good
    • 0

http://dobon.net/vb/dotnet/process/shell.html
からの抜粋ですが、引数は、別ですればよいと思います。

System.Diagnostics.Process.Start("cmd.exe", """/k winsat formal -restart clean""")

の1行で良いですが、以下の方をお勧めします。

'ProcessStartInfoオブジェクトを作成する
Dim psi As New System.Diagnostics.ProcessStartInfo()
'起動するファイルのパスを指定する
psi.FileName = "cmd.exe"
'コマンドライン引数を指定する
psi.Arguments = """/k winsat formal -restart clean"""

'アプリケーションを起動する
System.Diagnostics.Process.Start(psi)
    • good
    • 0
この回答へのお礼

早速のご回答、ありがとうございました。
なるほど、ダブルクォーテーションで囲うのですね。
しかし、2パターンとも試しましたが、最初と同様のエラーが出てしまいました。
これはもはや私の環境が影響しているのでしょうか?

お礼日時:2016/05/07 22:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています