C#, C♯, C#相談室 Part95
■ このスレッドは過去ログ倉庫に格納されています
■Visual Studio 2017 Community(無償の統合開発環境)等はこちら
http://www.visualstudio.com/downloads/
■コードを貼る場合はこちら
http://ideone.com/
■前スレ
C#, C♯, C#相談室 Part94
http://mevius.2ch.net/test/read.cgi/tech/1492843013/
■次スレは>>970が建てる事。
建てられない場合は他を指定する事。
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured >>798
過去一度でも表示されたことがあるか、なら、確実に一度は表示されている。(初期画面のタブなので)
そして一応、直前に表示した状況でも試してみたが、やはりPerformClickは反応しない。
(「スクリプト実行ボタン」と「スクリプトから押したいボタン」が同一TabControlの別ページにあるので、
タブを切り替えた直後に実行ボタンを押してみたが、駄目だった)
ただしその挙動は少し覚えがあるというか、
大量にコントロールを並べていて描画がもたつく場合、タブを切り替える毎に再描画している雰囲気はあるから、
それに近い可能性(見えてないタブのコントロールを剥がすとか)もありえるとは思う。 リファレンスには書いてないっぽいけど
ControlのCanSelectがtrueじゃないとPerformClick()はイベントを発生させない
https://referencesource.microsoft.com/#system.windows.forms/winforms/managed/system/winforms/Button.cs,346
ボタン側を拡張したりボタンが呼び出してるメソッドを直接呼べない状況なら
素直にTabをSelectする以外にないんじゃないかな InvokeOnClick()呼べる?
こっちなら何もチェックしてないっぽいけど 別にボタン押すとこまで律儀に再現しなくても良いよ
イベントハンドラかその中で呼んでるサービスを直接呼び出せばいい >>799
なるほど確かに初回表示済みかどうかにかかわらず表示されてない時はダネだねw
これなら問題なかった
static class Extensions
{
public static void RaiseClick(this Control control)
{
var t = control.GetType();
var m = t.GetMethod("OnClick", BindingFlags.NonPublic | BindingFlags.Instance);
m.Invoke(control, new[] { EventArgs.Empty });
}
} >>800
おお、ありがとう。
ググりまくりはしたが、ソースコードをチェックするという発想はなかった。
> このプロパティは、System.Windows.Forms.ControlStyles の Selectable 値が trueに設定されていて、
> 別のコントロールに含まれていて、コントロール自体が表示され、
> 有効になっていて、すべての親コントロールが表示され、有効になっている場合に true を返します。
> https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.control.canselect?view=netframework-4.8#System_Windows_Forms_Control_CanSelect
なんだかよく分からんが、かなり条件が深いのは分かった。
CanSelectはリードオンリーだから、素直に表示させるのが一番マシなようだ。
>>801
InvokeOnClickもprotectedなので駄目のようだ。(C3767)
ただ、なんでCanSelectなんだよ?とは思ったので、なるほどInvokeOnClickか!とも一瞬思ったが。
何がしたいんだよこの仕様(CanSelect必須)は。
GUIが有効か見ているわけだが、それをプログラムからの操作に噛ませる意味はないはず。 >>803
ありがとう。
ただ、リフレクションは嵌る原因になるので出来る限り回避している。理由は以下。
・C#ならさておき、VC++だとググッてもヒットしない。
・ならば勿論C#を参考にするわけだが、本来同じCLRでMSILなので全く同一の筈なのだが、
何故か一部異なっていたりして、そこで嵌る。(というか嵌ったことがある)
勿論使ってはいるが。
ただ、確かに今回はリフレクションでも対応出来る状況なので、最終的には使うかもしれないけど。 IEコンポーネントの代替品って何? ChromiumベースEdge のものは既に用意されてるの? >>805
ならこれでも出来た。
何か気づいてない弊害があったらごめんね
public static void RaiseClick(this Button button)
{
var parent = button.Parent;
if(parent is TabPage)
{
button.Parent = null;
button.PerformClick();
button.Parent = parent;
}
}
個人的にはこういうバットノウハウ感全開のコードは嫌いw >>808
さすがに動的に剥がすのは色々副作用が発生しそうで怖い。
今のところ以下のコードでやっている。このままか、>>803にするかのどちらかだと思う。
if (ctrl->Parent->GetType()->Name=="TabPage") ((TabControl^)ctrl->Parent->Parent)->SelectedTab = (TabPage^)ctrl->Parent;
((Button^)ctrl)->PerformClick();
キャストが入ってうざくなっているが、要はボタンの親のタブページをその都度選択(表示)させている。
これで動いている。ただしタブが勝手に切り替わるので知らなければギョッとする。
直後に戻せばいいだけかもしれないが、それはそれで無駄にイベントが発生するし、とりあえず放置だ。
仕様だと分かったので諦めはつく。
しばらくこれで試して、問題がなければこのまま、といったところ。
現状TabControl内のTabControlなんて無いから、おそらくこの方法で問題ないと思っている。
(TabControlが入れ子になっている場合、おそらくリフレクションしかない) >>809訂正
× TabControlが入れ子になっている場合
○ TabControl内にGroupBox等があり、そこにボタンがある場合
809のコードだと直接の親しか見てないので、
TabControl内のボタンは階層的に直接TabPageに貼られている必要がある。
そうでなければ親を再帰で辿るか、リフレクションするか、だろう。 馬鹿がこんがらがってるイメージ
ボタンクリックのイベントハンドラを表示
private void button1_Click(object sender, EventArgs e)
{
//
}
始めの{と終わりの}の間をすべて選択する
右クリック クイックアクションとリファクタリングを選択
メソッドの抽出を選択
適用をクリック >>812
だよなあ
おそらく「ボタンを押すこと」が目的化してしまってる
クライアントの要件は多分そういうことじゃない >>812
その程度の話なら既に指摘されてるよw
イベントハンドラは動的に変更されるかもしれないし、
ラムダ式や引数で与えられるデリゲートかもしれない。
だから普通質問者さんの問題意識は理解できると思うよw
イキってる君以外の人にはw >>814
その動的に変わるかもしれない処理とやらを抽出するだけだろ?
Form: btnFoo.Click += this.Model.Foo;
Model: void Foo() => _foo?.Invoke(); // _fooは動的に変化するかもしれない
スクリプト(オレオレマクロの文法がわからんから例としてpowershell)
$form = $AppHost.Container.Resolve("MyForm")
$form.Model.Foo()
画面を見なくていいならより直接的に
$model = $AppHost.Container.Resolve("MyFormModel")
$model.Foo() なんかもうバカの壁だねw
ボタンのクリックをシミュレートしたいというのは十分理解できる話だし、
それをなるべくそのまま表現できるようなコードを書きたい、という動機も
普通に理解できる話だと思うんだけど。
>>815的な発想の問題点は、
(1) プログラマの意図と実際のコードに乖離がある
(2) だから呼び出しているメソッドが今本当にButtonのイベントハンドラに登録されているものと
同一であるか、という検証の必要性が発生する。
(3) ButtonのPerformClickの「仕様バグ」を回避するため、
という非本質的な目的のためにコードの設計に手を入れるのは本末転倒
なにが「だろ?」なんだろうね
スギちゃんかよだっせーwww >>816
それより前の問題としてプログラマの意図がまず間違ってんだよ
魚をさばくのにノコギリでやろうとしてる状態
そこを正してからじゃないと話にならない
正さずにむりやり進めようとしてるからボタンクリックエミュレートなどという頭の悪い発想に固執する
挙げ句の果に画面上で見えてないと処理が走らない(涙)なんてバカバカしい罠にどハマリしちゃってるわけだ
はっきり言ってリフレクションはハマりやすいからダメだなんて言ってる場合じゃないよ だいたいクライアントのやりたいことは自社アプケーションのオートメーションサポートだろうよ
それを素人の思いつきレベルの発想でUIのオートメーションに目的をすり替えたのが運の尽きだわな
レイヤの考え方が全くわかってないアマチュアの設計だからすんなりうまく行くはずがないんだ
見えてないと発火しないこと以外にいったいどんな罠が潜んでるかわかったもんじゃない
俺が提案した方法ならUIインフラに依存しなくなるから実行時の安定性と罠が少ないぶん高い生産性が期待できる アセンブリが自分や所属チーム/組織のコントロール下にないんじゃないのかな
違う理由かもしれないがそれと同じような制約下での話だと思われる >>796
>GUIの画面をバッチ処理しようとしていて
UiPathとかAutoIt使いな。 >>820
そういうときはUIAutomationかWinAppDriverを使うといいよ
どうせこのあと要求がどんどん増えてボタンクリックだけじゃ済まなくなるんでしょ
あとで苦労するハックはやめてマイクロソフトが整備してる道具を使おう >>819
まあその「俺のプログラムが一番だ」という姿勢は俺は嫌いではないし、
むしろプログラマは全員持つべきだとも思うけども、
動的結合の価値(意味)が分からないのなら、まずはそこを理解した方がいい。
現在、Clickイベントをエミュレーション出来ないGUIフレームワークなんて、存在してない。
リフレクションも割と一般的になりつつある。(常用するのはどうかとも思うが)
だから、使いどころはあるんだよ。
静的結合だけでやれ、みたいなのは言ってしまえばC++がそうだが、それでもRTTIは検討されている。
動的結合の価値は>>816も書いてくれているが、同様に以下でも触れられている。(これらだけでもないが)
https://www.atmarkit.co.jp/fdotnet/dotnettips/270performclick/performclick.html
言ってしまえば「実行速度を捨てて保守性を採る」わけであり、これが適切かどうかは状況によるので、
PerformClickやリフレクション等を使うこと自体が間違いだ、というのはさすがに行きすぎてる。
(なお既に言ったが、速度至上主義のC++は割とそういう思想だし、これも間違いでもないが)
ただそれはさておき、PowerShellは使ったこと無いから調べてみたが、確かに面白いものではある。
ポイントは、.NETオブジェクトをインスタンス化出来ることと、それらをパイプで流せる点か。
>>815を見る限り、C#等CLRな物ならリフレクションで内部の関数をぶち抜いて、自在に呼べるのか!
(名前があやふやだが確か)COMでも似たようなことをしていたMSならあり得るか!とも思ったが、
そうではなくて、自分で.NETクラスをインスタンス化して呼べるだけか?
まあそれでもリフレクションを使えば何でもありにはなるし、
.NETを使うだけで本式のバッチスクリプト環境が自動的に提供されてしまう、というのは画期的ではある。
ここら辺はMSの上手いところだとは思う。 >>816
俺も「仕様バグ」に近いものだとは思うが、おそらくMSはそう認識してないと思う。
理由は、.NETは比較的「仕様バグ」は少ない環境であり、これは、
・MSがガッツリ保守している
・バイナリ側がランタイムのバージョンを指定出来るので、改訂しやすい
為、「仕様バグ」を後方互換性の為に残す必然性がほぼ無いからだ。
少なくともobsolete(非推奨)にすることは簡単に出来るのだが、してない。
多分何か理由があるのだろうけど、俺には分からない。
なお後知恵だがDobonには書いてある。
> ただし、コントロールのCanSelectプロパティがfalseの時は、PerformClickメソッドは何もしません。
> 例えば、コントロールのVisibleプロパティがfalseの時、CanSelectプロパティはfalseとなります。
> https://dobon.net/vb/dotnet/control/performclick.html
Dobonは、というよりMSDN以外は基本的に見ないことにしていたのだが、妙な嵌り方をした場合は役に立つのかも。
なお他にも
> クリックの動作と同じ動きをするため、EnabledプロパティやVisubleプロパティが"False"の場合、
> PerformClickメソッドを呼び出しても何も実行されません。
> https://www.ipentec.com/document/csharp-simulate-click-event >>823
なにこの
メソッドにすりゃいーじゃん
以上の意味を見いだせない機能 >>823
そのリンクの先はかなりクソコードだから鵜呑みにしないほうがいいぞ
まあ2005年の錆びついたものだしもともと低スキル向けの記事だからしょうがないけど
この記事の悪しき前提はViewに処理をベタ書きしちゃってることな
本来ならViewとModelを分離してView上のメニューとボタンからModelの同じメソッドをコールするのが正しい設計な
ViewとModelを分離してModelがViewに依存しなくなればModelをUIインフラから切り離して独立させることができる
そうすればオレオレスクリプトでオートメーションをサポートするといった要求にも容易に応えることができるようになる
UI操作をエミュレートするなどという泥臭いハックに頼らなくて済むのだ >>826
このページのコードと用例が糞なのは事実として、エミュレーションが適切な場合もあるってことだよ。
だから現在の全てのGUIフレームワークはエミュレーション出来るようになってるし、
リフレクションも装備しつつある。
MとVを厳密に分離してVはMのラッパ扱いに留めろ、というのは現在の思想としては正しいとして、
2005頃には今ほど言われていなかった、というより、そのころの失敗を経て現在の思想があるわけだから、
このページに対してそれを言ってもしょうがない。
ただそれにしても、現在もまだエミュレーションの価値はあると思うよ。
今回の点に関しての不満なら、俺は
MS:「OnClickがprotectedで呼べないからPerformClickを用意しました」
俺:「なら最初からOnClickをpublicにしとけよ」
であって、private至上主義という勘違いオブジェクト指向の面影を.NETもまた引きずっている点についてだね。 エミュレーションの有用性が分からないのは根本的に経験が足りない。
何故現在の全てのGUIフレームワークがその機能を持っているのか、その意味をよく考えた方がいい。
そしてそのレベルの奴がコードの善し悪しを議論するのは5年早い。
ただ、このレベルの初心者と話をしても意味がないから俺はやる気無い。
お前らが正しいのなら、MSは数年以内に.NETからエミュレーション機能、
つまりPerformClick/OnClick/リフレクション等を全削除することになるが、
俺はこれはあり得ないとしか思えない。
正否は結果で判断でいい。
ここで低レベルな水掛け論をやる意味はない。 こんなクダンネーモン作ってる暇があるならメッセージボックスが後ろに回らないように修正しろ >>827>>829
UI操作をエミュレートする需要があることは間違いではない
がしかしそれはUIコンポーネント実装のためだったりテストフレームワークのためだったりソースにアクセスできないGUIアプリケーションのオートメーションのためだったりであって
自社アプリにオートメーションサポートを実装するための基盤ではない
それをサポートを実現するまっとうな設計はUI層に依存しないAPIやCLIの提供であってUI操作とは全く逆の考え方だ
お前はノコギリにだって役目と需要があると言ってる
しかしノコギリは魚をさばくのには適さない
無論無理をすればノコギリで魚をさばくことはできるがそれはバカのやることだ >>832
あんたも相当しつこいねw
俺は質問者さんと別人だけど、ボタンやメニューのクリックをシミュレートしたい
場面というのは実際問題しばしば存在するよ
例えばクリックすると何か処理が走るボタンが複数あるとする。
この時、これを全部クリックしたのと同じ機能を果たすボタンが欲しい、
なんていうのは割とありがちな話。
あと、クリックで同じ機能を果たすボタンとメニューが存在する、なんてしょっちゅうある。
この場合はメニューの方のクリックをシミュレートするのが普通だと思うから
件の話を正当化する材料にはならないけどね。 >>834
えー、それにこれ使っちゃうのはキチガイだろ
チェック関連全部走ってから
本処理行くだろ >>832
「UIに依存する」のではなく、「UIの代替を提供する」のであって、
UIが変更された場合にはUIと同じく変更されるのが正しいんだよ。この点が違う。
そしてソース変更無しで自動追従させる手法がエミュレーションになる。
「UIに依存する」というのは、UIとは本来関係ない事をUIを通してやってしまっていることにより、
UIが変更された場合に動かなくなって困る(動作が変わってしまう)ことを言ってるだろ。
そうじゃない。今回はそこは動作が変わるのが正しいんだよ。
それはさておき、PowerShellって流行ってるのか?
思想が面白いのは認めるが、これはつまり「.NETアプリをライブラリとして公開する」訳であり、
ガチのプログラマに対してソース公開して、後はお前が頑張れ、と言っているに近い。
勿論これで行ける奴はいいが、実際のところ、使う側はアプリを使いたいのであって、
ソースを読みたいわけでもなく、プログラミングしたいわけでもない。
そしてアプリと完全に密結合してしまうから、そもそも同レベルのプログラマじゃないとソースは読めない。
だから現実的に、アプリ+PowerShellで何とかしろ、と言われても、プログラマでも困ると思うが。
ただし再三言っているが、思想が面白いのは認める。
これにより、全ての.NETアプリはPowerShellライブラリとして動作し、
また、ガチのスクリプト環境が手に入るわけだ。これ自体は(有用性はともかく)面白い。 >>834
どちらもボタンクリックをエミュレートする必要はない
上の例はクリックで実行される処理を順に実行するだけ
下の例はメニューとボタンから同じ処理を呼ぶだけ >>836
つまりお前が言いたいのは
スクリプティング機能の定石に反する糞仕様こそを求めているので今回に限り馬鹿なことをするのが正しい
ということか
PowerShellは流行ってるというかWindowsのシステム管理ではほぼ必須
OSにプレインストールされてるから開発環境用意するまでもないちょっとしたツールを作るのにも便利
今まさに話してるDSLを手軽に実装するための基盤としてもしばしば使われる
LinuxやMacで仕事してるなら触る機会ないだろうけどWindowsで開発してるなら触る機会は無数にあるはず >>796
おいもうそろそろこの話題締めて他所にいってくれや。 ふらっと荒らしてこっち荒らして、いつも同じメンバーだろこれ もともと完全にちゃんとGUI操作したいなんて書いてないだろさ
途中から見てる人が勝手に条件を足してるだけで本来あるべき姿とかい離してる
途中で無駄にリフレクションが出てくるあたり初心者の匂いが出てる
ボタン押すにはタブを切り替えなくてはならないのに
画面が変わらないままでボタン押したいって言ってるから別にGUI操作自体を再現したいわけじゃない >>838
違う。定石に反しているのは君の方で、つまりはカッコイイソリューションを目指しすぎている。
馬鹿みたいなソリューションの方が、現実的に使いやすいことは多々ある。
多分、ちょっと若すぎて元気がありすぎるのだと思う。
これ自体は悪いことではなく、むしろ上達には必須の性格で、良いことだとは思うが、
世の中のアプリがどうなっているか、もう少し周りを見た方がいい。
GUIの自動化で一番簡単なソリューションは、GUIを記録してしまうことだ。…(A)
俺が昔使ったアプリだと、「ログ画面」にGUI操作と等価のコマンドが一々流れる、というのがあった。
そして自動化したい場合は、このログ画面内の該当部分をコピペしたファイルを読ませるだけ、というものだ。
当然、見れば分かる程度であり、例えばファイルを読み込んだらそのファイルパスがまんま表示されている。
なら、そこを変更するだけで同じ処理を他ファイルに適用出来るよね、というわけだ。
冷静に考えれば分かるが、Unixのshもこれと同様だ。(というより上記方式がshのパクリだが)
shもhistoryで出てくる履歴をコピペすればバッチファイルになるようになっている。
そして必要なら該当部分を変数化してループを回せ、ということでしかない。
俺は使ったことないけど、Webブラウザの自動化ツールとして有名なSeleniumも以下見る限り似たようなもんだ。
https://www.valtes.co.jp/qbookplus/509
だから、初段階のスクリプト環境はこの程度でいいし、実際、この程度でも相当有益なんだよ。
そしてそれを手っ取り早く実装する方法がGUIのエミュレーション(PerformClick等)になる。
だから、
> 自社アプリにオートメーションサポートを実装するための基盤ではない
これはちょっと意識が高すぎる。(気持ちは分からなくもないが)
PowerShellでオートメーション、というのはその先の先の先位で、
初期段階に於いては超オーバースペックでしかない。
そして殆どのアプリでは最終的にも必要としない。 例えば上記アプリ(A)方式だと、ループ機能すらないのだから、
アプリ(A)だけで100個のファイルに同じ処理を適用しようとすると困る。
そこでループ機能を、とか言い出すと色々他が必要になって結局PowerShell、という思想もありだが、
そうではなく、Perl等でファイル名だけ変更するスクリプトを作り、
それでループを回して作ったドベタに展開された糞長いバッチファイルをアプリ(A)に流し込む、
というのもありなんだよ。
全ての処理を自アプリでやろうとするから無理が発生する。
unixはこれと逆で、他コマンドで出来ることは自コマンドでするな、で上手く行ってるだろ。
ソースコードについてもそうだが、アプリについてもKISS原則は重要なんだよ。
そして話を戻すと、UIの自動化のド定番は「実際に行われたUIを記録してそのまま流すこと」であり、
「PowerShell等のガチスクリプト環境と連携すること」ではない。
だからクリックエミュレーション等も今のところは今後とも必要な機能でしかない。
が、まあ、PowerShellを推す気持ちも分からなくはない。
おそらくIEだとPowerShellで自動化出来ると推測されるので、
IEが天下取っていたときに自動化の流れが来てたら少しは違ったかもしれん。 >>842
無知すぎて呆れる
世の中のサービスやアプリをちゃんと見てみろ
APIやCLIをサポートすることは多々あってもGUI操作をサポートしてるものなどごく少数派だ
UIとは読んで字のごとくユーザーのためのインターフェースであって自動化のためのインターフェースではない
APIとはアプリケーションプログラムのためのインターフェースであり自動化をサポートするならこちらを提供するのが当然の選択だ
APIやCLIのサポートが定石であってGUI操作は邪教徒の好む黒魔術でしかない
お前の常識は多分10年か20年前の辺境の集落での常識だ
現代のグローバルスタンダードに追いつく努力をしてくれ >GUIの自動化で一番簡単なソリューションは、GUIを記録してしまうことだ。…(A)
>俺が昔使ったアプリだと、「ログ画面」にGUI操作と等価のコマンドが一々流れる、というのがあった。
>そして自動化したい場合は、このログ画面内の該当部分をコピペしたファイルを読ませるだけ、というものだ。
>当然、見れば分かる程度であり、例えばファイルを読み込んだらそのファイルパスがまんま表示されている。
>なら、そこを変更するだけで同じ処理を他ファイルに適用出来るよね、というわけだ。
これ、昔作ったことが有るけど、最も上手くいった方法はMVCを徹底して、Cの入り口でコマンドオブジェクトをシリアライズして記録するパターンだったな
やってみればわかると思うけど、画面コントロールの操作ログを正確に記録するのも、再生するのも、一筋縄ではいかない COMで解決された問題を20年以上経って議論してる・・・ この話題をすり替えつつ自分の正当性をゴリ押しするスタイル、最近見ましたよね
明後日くらいには全然違う話題になってるぞきっとw 荒らしてるの毎回同じ人だよね
書き方に癖があるからすぐわかる >>837
繰り返しになるけどね、そういう「プログラマの意図と実際のコードに乖離がある」
ことをやると別の仕事が増えるでしょ。
ボタンABCDEが全部クリックされたのと確実に同じことが起るって誰が確認して保証するの?
ボタンABCDEのクリックイベントの処理を後で変更した時、またそれをやりなおすの?
その確認作業を忘れたらどうするの?
こういう後の保守のことを考えないプログラマは愚鈍で無能。
倒錯してるよ君。
「する必要はない」のは、「クリックで実行される処理を順に実行する」なんて保守性を下げる
アホな手段を採用すること。
なぜ素直にボタンクリックをシミュレートしようとしないの。 >>849
プログラマの真の意図は
ボタンを押したら複数の一連の処理をまとめて実行したい
メニューとボタンで同じ処理を実行したい
だろ
君が好きなボタンをエミュレートする方法は上記のプログラマの意図を実現する遠回りなやり方の1つだ
誰が確認するの?確認忘れたらどうすんの?なんて質問は自分は仕事でコード書いたことありませんと言っているようなものだから控えたほうがいい
テストを自動化するか人がやるか誰がやるかはチーム次第だがいずれにせよテストをしないわけがないではないか
そしてテストをするのはボタンをエミュレートする方式だろうが他のどうな方法だろうが同じことだ
まるで暗にエミュレートならテストを省略していいような言い方をするとああこいつはアマチュアなんだなとバレてしまうぞ
ちなみにテストの心配をするならなおさらUIに依存しない方式で書いたほうがいい
そうすればテストの自動化が容易になるから君が気にしてるテスト工数の増加やリグレッションの発生確率も最小化することができる
UIのエミュレートが正しく行われたことをテストするのはUI非依存のテストと比べると面倒な作業だよ
まあこんへんはアマチュアにはわかりにくいメリットかもしれないね Seleniumデザインパターン&ベストプラクティス、2015、オライリー
この本は、Ruby, Selenium WebDriver でのテスト手法を書いた本
例えば、Ruby, Selenium WebDriverで、
Yahoo への自動ログインするスクリプトは、下を参照
【VBScript】WSHについて話し合うスレ【JScript】
https://mevius.5ch.net/test/read.cgi/tech/1578522041/27 そしてさも当然ように混じり込むいつものRubyキチ >>844
だから君は意識が高すぎるんだよ。
誰もAPIを欲してないし、スクリプトを書きたいとも思ってない。
GUIを自動化したいだけ。
そして君だって、1つや2つのファイル名の変更は、普通にエクスプローラで行うだろ。
勿論APIは整備されていて、コマンドプロンプトでren fileA fileB と打つだけなのに。
GUIの方が簡単だから、GUIで済む場合はGUIを選択する、これが普通だ。
勿論100個と言われたら考えるが、10個程度なら普通はそこでAPI調べてDSLとはならない。
理由は、10個程度なら我慢出来る範囲で、DSLを書く方が時間がかかるからだ。
そしてこの原因は、DSLの方言が酷く、オレオレアプリのDSLなんて書いてもすぐには動かないからだ。
だから「今やった操作をする為のスクリプト」が吐かれ、それをコピペすればすぐ動く、というのは優れたAPIではあるんだよ。
ただ、根本的な原因は既に言ったが『方言が酷すぎる』事だから、それをPowerShellで統一する、という野望は、
方向性として合ってるから悪くもない。
でもそれが達成出来てるとは全く思わないけど。
Unixの「テキストファイル/テキスト操作ツール群/ファイル操作」で統一しているシステムが出来が良すぎて、
結局WindowsもWSLやDockerを導入してる有り様だろ。
話を戻すと、PowerShell+APIでPerformClickが不要になる、なんて事にはなってないし、今後ともならないよ。
GUIの方が直感的で簡単だから世の中GUIな訳で、その操作を自動化するのならエミュレーションは一つの正しい解だ。
ただ、PowerShellの野望は面白いと思うし、なったらなったで俺は普通にそっちに乗っても問題ないけど。
そしてPowerShellが本当に面白いのは、.NETアプリならリフレクション使って何とでも出来ることだろ。
プロセスへのアタッチ機能も有るようだし、APIなんて無くてもやりたい放題だ。
これが、そそる、というのは分かる。 >>845
それがすんなり行くかどうかはアプリの作りによる。
例えば、VSのコンパイル機能は csc.exe へのフロントエンドでしか無く、コマンドラインオプションを作るだけの物ではあるだろ。
こういう場合は至って簡単で、そのまま吐くだけで済む。
上手く行かなかったとしたら、前回の内部状態と混線したのだろうけど、ぱっとは思いつかないね。
普通にアプリを作ってしまえば当然再現性はあり、
どのボタンを押したかをそのまま記録/再生すれば当然同じ結果は生成される。
それらを「人間が見て分かるそれなりのコマンド名」に落とし込むのは大変だろうけど、ぶっちゃけ、
CONTROL Button インスタンス名 Click
程度のDSLならその心配もない。
これ以上に格好良くしようとすると、色々大変なのは分かるが、正直、この程度でもDSLとしては十分だから問題はない。
(ちなみに一応言っておくと、Buttonのみならず、他全て、例えばradioButtonやNumericUpDown、TextBox等、
内部状態を変更するGUIコンポーネントについては全てこの方式で記録/再生してる。
そりゃ再生出来るに決まってるだろ、というのは分かると思う) >>853
いやいや誰もUI操作を自動化したいとは思ってない
UI操作の背後で行われてる処理を使ってマクロを組みたいんだよ
ユーザーは無知だからUI操作をエミュレートする方法しか思いつかないんだろうけど開発者はそれじゃいけない
俺は名前変えるときでもコマンド打つけどねgit mv a bってさ
つうかそういう話じゃないよ
普段GUIで作業してようがなにしようがオートメーションしたいならGUI操作じゃなくAPIが整備されてたほうが嬉しい
それが当たり前の感覚であってAPIよりGUI操作のほうがいいなんてのは変人の考え方だ
UI操作するオレオレDSLなんてまあバグだらけだろうな
UI操作の不安定さなんてテスト自動化してる人なら誰でも身を持って経験してるからエンドユーザに提供するマクロ機能としてUI操作を強要するとかありえん
UI操作に加えてDSLまで独自開発なんてしてたらバグだらけのうえに開発機能までショボくて使い物にならんだろうな
PSみたいな既存言語に乗せればインタプリタの開発はマイクロソフトとコミュニティがやってくれる
デバッガなど含めた開発環境もノーコストで手にはいる
ユーザーは快適な環境でマクロを弄ることができるわけだ
オレオレマクロのユーザーは不憫だな
PerformClickはUIコンポーネントの開発者などが使うかもしれんから不要にはならないだろう
だがオートメーションサポートするのに依然としてPerformClickは必要ないな
UI非依存のAPIを提供するだけでいいのだからUIを操作する意味がない
人間が操作するときに直感的でわかりやすいといっても自動化に適するわけでもあるまい
自動化したいなら人間ではなくプログラムから見て呼び出しやすい構造を提供する必要がある
それはアプリケーションプログラミングインターフェースのことであってUI操作ではない
PSの面白いところはリフレクションとか意味わからんこと言うな
PS普通に使っててもリフレクション使ったコードなんて滅多に書かねえよ 処理の冒頭だけで途中でメッセージボックスが表示されてさらにユーザの追加入力が必要な処理はこれ使えねぇだろ
まさにゴミだろキングオブゴミだろ ThreadPool を使って、非同期に処理を実行しています。
特定のタイミングで ThreadPool に溜まっている処理を全て削除したいのですが、どのようにすればよいでしょうか。
// Threadの登録
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod));
// ThreadMethod の処理が終わる前に abort させたい
スレ違いなら、誘導してもらえると助かります。 >>857
CancellationToken(CancellationTokenSource.Token) >>850
なんか話が噛み合ってないね。
ボタンABCDEを全部クリックしたのと同じことが起るボタンが欲しい、という要件が発生した時、
その責務をモデルに持たせるべきか、むしろUIレベルでやってしまった方がよいかは微妙で
ケースバイケースだと思う。
俺は後者の場合の話をしています。
これまでの流れからそれは自明だと思うけど。
どうでもいいけどこういうのってemulat"なの?
simulateでしょ?俺の認識がおかしいのかな。
emulateって言葉はこの世界ではハードウェアの機能をソフトで代替するって
ニュアンスが強いと思うんだけどどうかな まああれだ、ボタンクリックをシミュレートするなんてなんかダサい、という
中二病的な発想は(同意はできないけど)理解はできないでもない
そういう人は「プログラマの意図と実際のコードに乖離がある」 ことの方には気持ち悪さを感じないんだねw
っていうか理解できないのか。>>850の人もそうだと思うけど。
だから、プログラマの意図というか要件は「ボタンABCDE全部が押されたのと同じことを起こすボタンが欲しい」
なんだけど。 俺なら「ボタンが同時に押されないように作る若しくは押されても一つだけ有効にする」で組む方を優先するわ >>860
微妙、ではなくモデルに持たせるのが正解
>>861
中2とか意味わからん理由ではなく実益をとっただけ
理解しやすさ、テスタビリティ、変更への耐久性、等を考えればボタンクリックは、無い
プログラマ意図をコードに反映することは良い習慣だが
判断を誤ったプログラマの意図をコードに反映させることを正当化してはいけない
まずは判断を正してから意図をコードに落とし込もうね ワッチョイ 477b-yNzz
ブーイモ MM0e-BzDP
アウアウウー Sac3-+wK4
いつまで続ける気だよ役立たずどころかクソ迷惑 >>864
C#のスレでFormsについて話し合うことの何が問題なんだ?
もともとはVC++だったけどこの話題はC#でも通じる話だからここで話してもなんの問題もないはずだ >>855
まあ君がどうしてもPowerShell推しなのはわかった。
> UI操作するオレオレDSLなんてまあバグだらけだろうな
それはオレオレDSLに無理に高度な機能を持たせすぎてるから。
つるんと書かれたDSLをただ上から順番に実行するだけ、しかもエミュレーションの時に、
何行のコードを追加し、何行の既存コードを変更する必要があると思ってるんだ?
面倒だから答えを言ってしまうが、追加が30-50行程度、既存変更は0行、つまり変更無しだ。
エミュレーションが開発的に強烈なのはこの、完全に外付け出来る点だ。
>>849,850の争点もここで、俺は849と思想が同じく、「そもそもテスト項目を増やすな」でしかない。
だからバグっててもDSLモジュール内で閉じてて精々DSL機能が使えなくなるだけで、
追加テストはエミュレーション部分のみ、というのは十分魅力的なんだよ。
そして君はAPIAPI言っているけど、PowerShellには特にAPIを用意する必要があるわけではないだろ。
publicにしてある関数を勝手に呼ぶだけ、精々ドキュメントを整備するくらいだ。
当然リフレクションを使えば内部関数等は全部抜けるので、呼ぶだけならいくらでも出来る。
リバースコンパイラを使えば分かるが、リフレクションでも割と読めるコードが得られる。
後は好きなだけハッキングしろ、でしかない。(これを、そそる、と言っている) あと、PowerShellにこだわりすぎて、強力なDSLなんてPowerShellでしか得られないと思ってないか?
気づいていないんだろうけど、「テキストファイルで操作する」というのはUnixのAPIであって、
そこに揃えるだけでUnix周りのツールが全て使えるようになるんだよ。
具体的に言うと、DSLソースをファイルではなく標準入力とすれば、
(一応言っておくがC#等GUIアプリもコマンドラインから起動すれば普通にパイプできる)
その前段のツールが標準出力に「CONTROL Button instancename Click」と吐きさえすれば自動化できるのだから、
PowerShellみたいな糞文法につき合う必要もなく、言語も選べる。当然、C#やPythonも使える。
これも一応具体的に言っておくと python myscript.py | my.NETapp.exe な。
だから高級なDSLが欲しいにしても、フルスペックのDSLを自前で持つ必要なんてまるでなくて、
自アプリ内はアホみたいに「食わされたコマンドを処理して終わり」なDSL実行部分だけで十分なんだよ。
それで後はAWK/Perl/Python/Ruby等、好きな言語使って勝手にやってくれ、になる。
つまり30-50行程度追加し、既存部分にバグが発生することもなく、
AWK/Perl/Python/Ruby等好きな言語を使って自動化出来るのがエミュレーションの利点であり、
Unixインタフェースに揃える美味さだ。だからみんなここから離れられない。 >>860
一応調べてみたが、この場合は微妙だし、どっちでも良いと思う。
> https://hinative.com/ja/questions/11390949
> https://xcelgo.com/emulation-vs-simulation/
要は、中身まで模倣するのがemulationで、外面だけ合わせるのがsimulation。
よって実行速度は通常simulator>>>emulatorになる。
void Button_Clicked(Object^ sender, EventArgs^ e) {
some_func();
}
で some_func を直接呼ぶならsimulation、
Button_Clicked を呼んでもまあsimulation、
OnClick や PerformClick を呼ぶならemulation、というのが俺の見解。
emulation扱いの2つはClickイベントを発生させる=UIスレッドのイベントキューに積むだけであり、
ハードウェアマウスのイベントと見分けが付かないから。
(内部的にハードウェアマウスのクリックを模倣している)
対して上記simulation扱いの2つは、
simulatorが「このボタンをクリックしたら結果的にこの関数を実行する」と知っていて、
外面動作を合わせる為にそこを呼んでいる。
当然emulationの実行速度はsimulationと比べて遅い。
だから、最初からsome_func()呼べよ、という若さは分かるが、そこをケチっても実質的意味はない。
ここら辺は年を取れば老獪になるというか、手の抜きどころが分かるようになる。
emulation方式だと当然、UIスレッドがハングアップしていたら永久に処理されないし、
未処理のイベントがあればその後に処理されることになる。
ここら辺は完全にハードウェアマウスの動作と同じになる。
simulation方式だと、すぐに呼ばれる為、
非UIスレッドでDSLを処理した場合、未処理のUIイベントがあると処理順序が逆転してしまう。
だから、DSL実行環境とGUIの実行環境が同一の場合はDSL処理はUIスレッドでやるしかない。
だったら最初からPerformClickでやればそういう心配すらないだろ、ということになる。 余談だが>>850のUIテストが安定しないのはこの辺が大きい。
要は、GUIなんて所詮人間相手前提で組んであるのであって、
CPUの速度でイベントを積まれた場合にも正しく動くレベルまでのテストは為されていない事も多い。
技術的に見ればアプリが糞で組み方が悪いだけだが、そこまで保証する意味もないのも事実。
結果、「人間がやると動くが、CPUでやると動かない」なんてのは割とよく遭遇することになる。
だからまあ、「UIテストは安定しないから出来るだけ回避」も一つの戦術だが、
「UIテストも安定するようにちゃんと設計する」も一つの戦術なんだけどね。
「安定しない」のはあんまり正当化していい話でもないし、
ちゃんと設計されているアプリしか触ったことのない人にとってはポカーンな話でもあるとは思うよ。
ちなみに、文句を言っている連中に合わせるとしたら、以下のようなDSLにすればいい。
CONTROL Button instancename Click // PerformClickを呼ぶ
some_func() // some_func()を直接呼ぶ
これで、好きな方使えで済む話で、実際も、これに近い。
(当然だがDSL用のコマンドは別に持ってて、全部大文字なのはそれらと被らない為の方策) 議論が発散しててよくわかんないな。
何が何なの?全員、アブストを書いたらどうだ? >>866
論点をずらそうとしてるね
クソみたいなUI操作オレオレマクロよりUI非依存のPSのが低コストで品質がいいねというだけの話だろ
例としてPSを出したが別になんだっていいよ
最も大きな問題はインタプリタの方ではなくUI操作でオートメーションサポートするというバカバカしい発想の方な
オートメーションをサポートするならUI非依存のAPIを整備しろ
それが正しい道だ 話がまとまってないのに余談とか言っちゃって相手もそれに乗っかちゃって…
これを繰り返すからいつまで経っても収束しないし元の議題が何だったかわかりづらくなる >>860
>>868訂正、結果的に>>869は間違いなのでよろしく
俺の見解では全部simulationになる。
確認してみたら、PerformClickは同期イベントだった。
呼び出し履歴見る限り、Button.PerformClick->Button.Onclick->Control.OnClick->イベントハンドラ なので、
OnClickもほぼ確実に同期だと思われる。
だから呼称は全て simulation の方が妥当となる。
イベントキューとかは全く関係なくなるので、該当部分の869の話は間違いということでよろしく。
同期イベントなのは.NETの癌だと思っていたが、
この点に関しては同期イベントの方がプログラミングしやすい、というのは事実だな。
(俺の想定の非同期イベントだと俺のコードは動かないはずなのに気づき、確認したところ、同期だったorz) >>871
> 論点をずらそうとしてるね
お前がだろ。
> UI操作でオートメーションサポートするというバカバカしい発想の方な
GUIの自動化ならGUIのエミュレーションが俺的に第一選択肢だ。
これについては既に>>842で言ったとおり、君が気に入らないのはどうぞご自由にだが、
最近話題のSeleniumでも同様なのだから、君が思うほど糞でもないんだよ。
もっとも汎用的で、もっともカッコ悪いが、どんな馬鹿でも使えるソリューションだ。
そして、やる気になればPerlやPythonと組み合わせて自由自在でもある。
ソースコード戦略にも、テストにも問題がない。ならこれで決まりでいい。 >>874
Selenium系はAPIを提供してないサイトのオートメーションをユーザーが苦労して泣く泣く自動化したい場合やテスト自動化で使うツールな
俺らが今議論してるのはユーザー目線じゃなくて提供者側なんだよ
提供者側がAPI実装を放棄してGUI操作をサポートするなど馬鹿なことだ
ユーザーに苦労を押しつけてはいけない >>863
複数のボタンを全部クリックした時の動作、なんていう下らない機能を
モデルに持たせることが正当化されるケースってむしろあんまりないと思うよw
ぱっと思いつくのは、ボタンABCDEをクリックした時の処理に共通する部分
(例えばファイルのopen/closeのような前処理後処理)があって、まとめてやる場合には
大幅な最適化が可能な場合。
この人本当にプログラマかな。 >>870
白鳥はすべて白い(PerformClickなんて100%イラネ)という人がいるので、
いやいや世界には黒い白鳥もいるんだよ、とまあそういう話 >>876
その糞設計だと要件変化ですぐにコードが汚染されるだろうなぁ
処理は今までどおり実行したいが特定のボタンだけ画面から削除したくなったせいで謎のHiddenボタンを置いたり
処理の結果で後続の処理を分岐したくなったせいで不自然な制御フラグフィールドが乱立したり
画面のデザイン変えただけなのになぜか処理の実行順序が変わったり
少し想像しただけでトラブルの兆しがするするでてくる
こういう発想はアマチュアらしくて微笑ましいけど業務で見かけたら説教しなきゃいけないぐらいだ >>863
各ボタンに割り当ててるコマンドをcomposite Commandで繋いで終わりじゃない? >>878
よく分からない妄想ワロタw
意味が分からないよ
>要件変化ですぐにコードが汚染される
まさにその通りw
君の設計方針だと必然的にそうなる。 どーでもいい非必然的な機能をモデルに持たせることは、
UIにベタベタ処理を実装するのと同じ糞設計ですw 一応言い訳しておくけど、>>876に書いたみたいに最適化の恩恵なんかなくても
複数の処理をまとめて一度にやるメソッドをモデルが持つことが自然なケースはもちろん存在すると思う。
っでも俺が言っているのは「黒い白鳥もいる」だからね。
「白鳥は全部白いは間違っている」と言ってるだけだから >>880
お前のやり方はではすぐにコードが汚くなるって言ってんの
俺のやり方はメンテナンスしやすいモデルを採用してるからコードの品質が維持される >>882
まとめて処理をする機能が要件にあるならそれをモデルに実装するのが王道で自然な方法
お前はそれをボタンクリックなどという大道芸的な方法で実装しようとしてる異端 >>881
そうだ
だからまとめて処理をするという最小限の機能をモデルに実装せよと言ってる
ボタンクリックなどという余計なお遊びは入れなくていい こない未来を予測してる奴はバカ
絶対失敗する
しかも、最悪の形で >>886
来るかもしれない未来を考えないのも同じぐらい馬鹿だな
そして未来がわからんなら余計な拡張性を導入するのではなくコードを容易に改修できるようにシンプルに保つことが重要
つまりシンプルなモデルにやりたいことを素直に書けばそれでいい
それで済むものをわざわざボタンクリックなんていうやらなくていい遠回りな方法で実装するのは後で困る馬鹿の典型例 >>875
だから君はちょっと意識が高すぎるんだよ。
自動化したいユーザーは、今やったのと同じ操作を100個のファイルに適用したいとかだ。
「ログに出てるコマンドをコピペすれば今やった操作を自動化出来ます」との情報を得て、ログを見たら、
CONTROL TextBox filename my000.jpg
CONTROL Button file_load Click
CONTROL Button filter_A Click
CONTROL Button file_save Click
となってたら、まともなプログラマなら適当にスクリプト書いて10分後には完了してる。
そこを「APIを調べてPowerShellでスクリプトを書いてください」だと困る奴の方が多いと思うが。
何でオレオレアプリのAPIをユーザーが一々調べないといけないんだよ?調べるだけで10分かかる。
方法は何でもよく、勿論APIでもいいんだけど、ユーザーは手っ取り早く今の処理を100個のファイルに展開したいだけ。
それには歴史的にも今も「テキストファイル内にコマンド羅列(=つまりスクリプト)」という方法が用いられている。
これが一番分かりやすいからだよ。
PowerShellの「.NETアプリをインスタンス化して内部関数を直接呼ぶ」というのは発想としては面白いけど、
それが分かりやすいわけでもなく、汎用性があるわけでもなく、使いやすいわけでもない。
まあもうこれは堂々巡りだから終わりでいいが、
君の意見が正しければ、今後は全てのアプリでAPIが公開されていき、MS謹製のUIAutomationなんてゴミになることになる。
俺はそんなことにはならないと思うけど。 >>888
だからよ
1処理用の処理を連続で100回動かしたら確認ダイアログが100回出るだろーが
バカかテメーは >>888
意識は高くない普通の感覚だよ
当たり前のことを当たり前にやるだけだ
モデルに処理を書いてビューに紐付けるってごくごく自然なコードだろ
しかもそれすればほとんどタダでオートメーションサポート機能が手にはいるんだぞ
ボタンクリックとかわざわざ苦労してトラブルを持ち込んでくる意味わからねえわ
マゾなのか >>889
その程度の回避策が思いつかないようなバカがいるとは >>888
ちなみにこのマクロでわかりやすいと思うのはお前だけだぞ
普通の人だったら
オートメーションなのなんでコントロールを操らないといけないんだ意味わからん
ボタンとかテキストとか書かれても何やってるか意味わからん
各行の関連性が意味わからん
操作してるインスタンスはどのフォームだよ意味わからん
などなど大混乱してしまう
ユーザーが見てわかりやすいレコードログってのは↓こういうものな
$model = $MyAppHost.Resolve("MyModel")
$model.FileName = "..."
$model.LoadFile()
$model.FilterA()
$model.SaveFile()
この処理をたとえばカレントディレクトリ全体に適用したいなーってユーザーが思ったらls | foreachでパイプするだけ
お前の大好きなコード生成みたいなバカバカしい無駄な苦労をしなくて済む >>892
そこ工夫が必要ならこんなくだらんメソッド呼ばんわw >>888
例えばさぁ
お前のオレオレうんこマクロでファイルが存在しなかった場合のハンドリング処理はどうやって書くつもりなんだ?
ファイルの形式が間違ってた場合は?
セーブに失敗したときどうする?
指定したディレクトリツリーのファイルすべて処理したいときはどう書くんだ? 直のWINAPI(というか多分アンマネージ)が混ざる動作だとDebugとReleaseで動き変わること割りとあってめんどくさいな WINAPIのはDebugだと0埋めされるんだろ
そりゃ動作変わるって(バグがあればω) 0じゃなく埋められる数値は何種類かある
デバッグリリースで挙動変わるのはほぼ確実にメモリ周りでなんかやらかしてるね ■ このスレッドは過去ログ倉庫に格納されています