107077
UWSC 仮 掲示板
投稿時に「証明書が不正です」と出る場合には、JavaScriptをオン
動作不具合での質問の場合には環境を表記(OS,バージョン等)
タイトルは内容を表し、内容はネットゲーム関係禁止
自身でコードを書く気の無いナマケモノは特に質問禁止
失敗作でもコードを投稿すること(具体性の無い質問は無視される可能性大)

UWSC掲示板 が復活することを祈り、それまでの繋ぎとして。
環境設定[s7777777]

動作確認 / sousou
お世話になります。
uwscを起動すると、タスクマネージャにUWSCが動作中であることが表示されているのですが、たとえば、fukidasi("10秒");sleep(10);
と吹き出しやsleepなど、各動作にたいしても、パフォーマンスやアプリ状態など、PC内のどこかに各々の機能が動作していることを見つけることができますでしょうか。
自分なりに探してみましたが、変化がわからなかったので、ご教授いただけますと幸いです。

No.1214 2021/02/23(Tue) 10:10:04

Re: 動作確認 / stuncloud
実行している関数毎のパフォーマンス?が得たいということですか?
> PC内のどこかに各々の機能が動作していることを見つけることができますでしょうか。
申し訳ないんですがちょっと何が言いたいのかがわからなくて回答に困りますね…?
基本的にはuwsc.exeの状態を監視するほかないと思います…よ…?

https://stuncloud.wordpress.com/2013/08/19/uwsc_perfmon/
僕は昔こんなことしてたようです
関数を呼び出す前から呼び終わった後のパフォーマンス計測なんかはこれでできると思います

それとも、どのタイミングでどの関数が呼ばれていたかを確認したいというのであれば例えば

print "sleep(10)実行中"
sleep(10)

といった感じで逐一printしておけば
・(print窓を見て)今sleepが呼ばれている
・(printが吐いたログファイルを見て)何時何分にsleepが呼ばれた
といった情報は得られると思います


どのような目的でどのような情報が必要か?を具体的に書いていただけるともう少し的確なアドバイスができると思います

No.1215 2021/02/23(Tue) 15:38:51

Re: 動作確認 / sousou
ありがとうございます。
実行している関数毎のパフォーマンス?が得たいということではありません。
実行している関数が、途中で制御できなくなる場合があり、いつもではないのですが、uwsc自体をタスクマネージャで消しても動作が停止しない場合があります。
uwscで、たとえば、sleep中である場合とsleepが停止された場合で、パフォーマンスということでなく、そもそも、uwsc自体の関数自体が、windowsの機能の部分を利用しているわけで、関数を利用=windowsのどこかの機能をつかっているはずで、それを、UWSCのログ等でなく、PC内のどこかで確認する手立てがないものか知りたく投稿させていただきました。
当方、そこらへん素人ですので、おかしなことを言っているかもしれませんが、ご勘弁ください。

No.1216 2021/02/23(Tue) 17:47:14

Re: 動作確認 / stuncloud
> たとえば、sleep中で
例えば、ではなく具体的にお願いします

> 実行している関数が
それはどの関数ですか?

> 途中で制御できなくなる場合があり
制御できないというのはどのような状態ですか?

> uwsc自体をタスクマネージャで消しても動作が停止しない場合があります
なんの動作が停止しないのですか?

> PC内のどこかで確認する手立てがないものか知りたく投稿させていただきました。
現時点では情報が不足しているためあるともないとも言い切れません
(状況によって確認する手立ても変わるので)

No.1217 2021/02/23(Tue) 20:48:09

Re: 動作確認 / cho
自分が考えている問題点を第三者に伝えようとするのは難しいですよね(語彙力)

sousouさんは問題を発見した。それを解決する方法を自分で考えた。
しかし、解決する方法を実現するのに、こんなことは出来ないかと質問した。

と言う感じでしょうか。先日の私のEVALの質問もこんな感じですみません。

ということで、問題の方を推理してみました。

?@ UWSCのSTOPボタンを押しても処理が終わらず、
  フリーズ状態になるのでタスクマネージャーで強制終了している。
  UWSCはタスクから消えるけど、UWSCによって起動されたWindowsの何かのアプリが処理を続行したまま停止しない。

?A STOPボタンを押して、毎回ではないけどUWSCがフリーズする。
  フリーズ(UWSCの処理が終わらない)の原因を見つけたい。
  関数を利用=Windowsのどこかの機能を使っている というのが解釈の違いになっている気がします。
  関数はWindowsの機能(DOSコマンドやpowershellなど)を使うこともできますが、明確に記述する必要があります。
  SLEEPやFUKIDASIなんかは、終了しても残るような別処理するWindowsの機能を使っていないと思いますよ。

?B タスクマネージャーで終了してもUWSCが消えない


たぶん?Aだと仮定して。
?Aであるなら、
 ・WHILEなどを使った多重ループ処理中にSTOPボタンを押すとフリーズする経験があります(SLEEPなしの拷問状態)
 ・タスクマネージャーでUWSCを見ると、UWSCが処理している状態
  UWSC(32ビット)(処理中の数)
  を確認できます。
  この中に、DOSコマンドを使った時に生成される
  Windows Command Processor や
  コンソールなんちゃら
 があると終了時にフリーズすることが多いです(回避策あるなら便乗して知りたいです)

その他の問題であれば、ぜひ質問内容を一問一答できるように整理して再質問お願いします。
(私は回答できる技量を持っていませんが・・・)

私もタスクマネージャーでUWSCの状態を取得したいと考えていた時期がありますが、
状態の変化を探す。ではなく、処理を順番に検証していって、どこの処理でフリーズする不具合があるか見つける方針が良いと思いますよ。

No.1218 2021/02/24(Wed) 14:50:52

Re: 動作確認 / sousou
stuncloud様、おっしゃる通りです、スクリプトの提示もなく、あいまいな質問でおしえていただきたいという甘い考えでした。
正直、ごちゃごちゃなスクリプトがだらだら長く重なっており、恥ずかしく提示できないことお許しください。
ただ、フリーズ?の原因は、こちらでそれこそ、1つ1つ、printなど分解確認して、時間をかけてでも自己解決しようと思っております。

cho様、ありがとうございます、ご推察の?@となります、確かに、WHILEを使った多重ループ処理中にSTOPボタンを押すとフリーズする(SLEEPなしの拷問状態)、まさに、このような感じです、タスクマネージャーで見ると、UWSC(32ビット)(処理中の数)を確認できるとのことですが、変化を確認できず、UWSC(32ビット)を消しても、処理が終わらない、ようやくして、何分か後に停止されるため、UWSC(32ビット)でない、怪しいのは、データを掴んでくる所と繰り返しsleepなので、たとえば、単純なsleep関数であっても、UWSC(32ビット)以外のどこかに、別の動きがあるはず、なればそこを無理やりでもそこをdosで停止させれば、単純に、処理が終わらないというようなことはなく、一瞬で処理を停止できるのではないかとの考えです。

質問の真意は、フリーズする不具合を見つけたいというのでなく、uwsc関数=Windowsのどこかの機能を使っている と思っていたのですが、そこが、違っているのか、そうでなければ、UWSC(32ビット)をタスクマネージャで消して終わらないのは、何故か、単にフリーズしているわけではないようなので。。(答えようないですよね)
ただ、スクリプトにcmdを使っているわけでないので、Windows Command Processor やコンソールなんちゃらのせいではないような気がしています、ぼんやりな質問回答でまことに申し訳ございません。

No.1219 2021/02/24(Wed) 16:34:42

Re: 動作確認 / stuncloud
> 質問の真意は、フリーズする不具合を見つけたいというのでなく、uwsc関数=Windowsのどこかの機能を使っている と思っていたのですが、そこが、違っているのか、そうでなければ、UWSC(32ビット)をタスクマネージャで消して終わらないのは、何故か、単にフリーズしているわけではないようなので。。(答えようないですよね)
今回のポイントはsousouさんが問題を認識しているものの原因がわからないので当たりをつけて(uwsc関数=Windowsのどこかの機能を使っている)みたものの、どうしたらいいのかさっぱりわからない、というとこなんですよね
こうなると自分が当たりをつけた部分に必ず正解がある、と盲信してしまうもので、そこからの解決方法を求めがちです
しかしこういった場合そのアプローチはほとんどの場合的外れであったりするものです
これは人類が抱える重大な不具合でわりと不可抗力な面はあります、だからそうなるのはしょうがない

で、今回sousouさんがどうすべきだったかというと
・ある関数を実行すると制御不能になる場合がある
・その部分はこのようなコードである(該当コードの抜粋)
・このような場合に試みたこととして
 ・タスクマネージャからuwscのプロセスをkillしたが不都合が生じた
というような感じで事実だけ伝えてもらうことだったんですね
そして
・uwsc関数=Windowsのどこかの機能
のような不確定な考察は別になくても良いです

大切なのは実際の現象とコードが提示されていることで
それを元にこちらも検証コードを書いたり再現性を詰めたりできるのです
(そして言うまでもなく100%再現するコードがあると解決も早いので理想なのですがこれがなかなか難しいんですよね)

ある程度調査されてそれでも行き詰まるようでしたらまたご質問ください
こういうケースは現象が起きてしまってから原因を取り除く、よりも現象が起きないようなコードを書くほうが良い場合が多いので、そっち方面での助言などもできるやもしれません

No.1220 2021/02/24(Wed) 18:56:51

Re: 動作確認 / cho
> WHILEを使った多重ループ処理中にSTOPボタンを押すとフリーズする(SLEEPなしの拷問状態)、まさに、このような感じです

この問題でしたら私にも経験があります。

> 何故か、単にフリーズしているわけではないようなので

「毎回フリーズするわけではない」というキーワードと、このフレーズで思い当たることがありますが、
もしかしてTHREADも使っていませんか?
メイン処理が多重ループのうえに、他に並列(THREAD)で多重ループを処理している状態。
このような場合は高い確率でUWSC終了時にフリーズします。

メイン処理を終了させたのに、並列処理が終了できない(ちょうどループ処理真っ最中)
運よく並列処理がループ中ではないか、SLEEP中などで終了処理を正常に受け付けてくれることもある。

Windowsの何かの機能でなく、UWSCの別処理が停止しないという現象でしたら、
先ほどの?Aに該当しそうですね。

でも、?@とおっしゃっていたので、ホントに何かのアプリが起動していて(フリーズ状態で)終了していないのかもしれません。

的外れでしたらごめんなさい。
的外れでなければ、再質問してくださいね。

問題は1つのコードに起因するものではなく、全体の構造にあるのだと思います。
一つ一つの処理は正常に動くからコードの提示がしにくいですよね。
初心者(私含む)が質問する時に躊躇するジレンマです(笑)

No.1221 2021/02/24(Wed) 21:23:20

Re: 動作確認 / satocha
> 正直、ごちゃごちゃなスクリプトがだらだら長く重なっており、恥ずかしく提示できないことお許しください。

ここで提示できるようスクリプトを整理する作業を行うことをお薦めします。

本質的でない処理をしているところは
print "〜の処理"
のようにまとめ、全体を整理して構造文(while〜wend、for〜nextなど)や関数呼び出しなど処理の流れがはっきり分かるようにしていきます。

実は、このような作業を行うことで自分で間違いに気づき問題が解決してしまうことも少なくありません。

コードを見せることは確かに恥ずかしいと思うかもしれませんが、コードを人に見てもらうことはプログラミング上達の近道です。

「コードレビュー」という言葉で検索してみるとそこらへんの事情が分かると思います。

No.1222 2021/02/24(Wed) 22:25:40

Re: 動作確認 / sousou
皆様ありがとうございます、頭が固いのでしょうか、どうしても、uwsc関数=Windowsのどこかの機能を使っているから、その何かがどこかにあるはず、それを知りたいという思いに囚われています、コードは、整理してできましたら、再度投稿という形でまた提示できるようがんばって見ます。
No.1223 2021/02/25(Thu) 07:50:51

Re: 動作確認 / しろまさ
固いと思います。
ほとんどの場合、問題はコード自体にあります。
思い込みに捕らわれず、関数を使って処理を機能別に細分化してください。
どこでその問題が起こるのかが判断できれば、対策もしやすいはずです。

No.1224 2021/02/25(Thu) 09:06:49

Re: 動作確認 / sousou
'対策'が目的ではでなく、Windowsの機能とソフト自体の質問でしたが、質問場所を間違えました、お騒がせしました。
No.1225 2021/02/25(Thu) 11:08:25
FCLOSE関数の引数をTRUEにした場合のデメリット / takahi
FCLOSE関数はデフォルト値が「エラーダイアログを出す」ですが
確かに書き込みエラーになったのに、それが分からないようでは不都合が起きると思っていたのですが、
最近「エラーダイヤアログを出さない」というオプションがあることを知り、
しかもそれは書込みが正常終了するまで再試行してくれることが分かりました。

「エラーダイヤアログを出さない」のデメリットが思いつかないのですが、
何かありますか? 
(※ 雑談で済みません)

No.1205 2021/02/18(Thu) 19:22:09

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / stuncloud
> しかもそれは書込みが正常終了するまで再試行してくれることが分かりました。
これがまさにデメリットになるかと思います
正常終了が不可能な場合に不都合が生じることが予想されます

それはそうと書き込みエラーが生じる状況がそもそもよくないのでそこはエラーハンドリングしたいですよね…
tryでどうにかなるのだろうか?

No.1207 2021/02/18(Thu) 20:08:55

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / takahi
なるほどですね
自分の場合は別プログラムからの読み込みと書込みがぶつかった時に出るエラーでしたので、再試行でいつかは必ず正常終了してくれていたのですが、
正常終了が不可能な場合は困りますね。

それにしても、プログラムを一旦中断させるのではなく、logにだけ残す仕様にしてもらいたかったです。

No.1208 2021/02/18(Thu) 23:32:11

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / stuncloud
try使えますね

try
 fclose(fid, FALSE)
except
 print TRY_ERRMSG // ファイルに書き込めない場合printされる
endtry

また、readonlyのファイルにfclose(fid, TRUE)した場合は、程なくスクリプトが終了していました
ちゃんと調べていないので最大リトライ回数が設定されているのか、あるいはreadonlyだったので処理をやめたのかは不明です

# UWSCRでは明示的にリトライできる仕組みにしようかな?

No.1209 2021/02/19(Fri) 11:05:52

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / takahi
済みません、Trueにしたら正常終了するまで再試行してくれる、と思ったのですが
間違いのようでした、、、

以下が私が検証用で使ったプログラムなのですが

//読み込み.uws
for i = 1 to 20000
f = fopen("test.txt") ; a = fget(f,1) ; fclose(f)
next

//読み書き.uws
r = 1
for i = 1 to 1000
f = fopen("test.txt",F_WRITE or F_READ) ; fput(f,r + " あいうえおアイウエオ " +i)
r = fclose(f,true)
next

同時に走らせると、デフォルトのままだとエラーが表示される、trueにするとエラーが表示されず
しかも変数iは連番で出力!と思ったのですが、
test.txtが大きくなるにつれて変数i は飛び番で出力されてしまいました。
単にtest.txtが小さいときはエラーにならなかっただけでした、、、汗

スキップされたのが気付かないのは運用上困るので、悩み中です。

#はい、リトライしてlogにだけ残す仕様にしてもらうと有り難い限りです。

No.1210 2021/02/19(Fri) 19:48:01

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / stuncloud
> スキップされたのが気付かないのは運用上困るので、悩み中です。
上にも書きましたがFALSE指定しつつtryで囲めばダイアログを抑制しながら書き込みエラーをexcept部で検出できるので、それで対処するのが良いと思います

// 例:書き込み失敗時は5回までリトライする
logprint(FALSE)
for i = 1 to 5
 try
  fclose(fid)
  break // 書き込み成功したのでforループを抜ける
 except
  // 書き込みエラー
  print TRY_ERRMSG // ログを書く
  sleep(5) // 5秒後に書き込みをリトライ
 endtry
next
logprint(TRUE)

No.1211 2021/02/19(Fri) 23:57:13

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / しろまさ
UWSCはfopen時に内容を全てメモリ展開しfclose時に保存する方式の為、
ファイルが大きくなってくるにつれ時間が長く掛かります。
排他無しで連続で開けた場合は最後に閉じたものが優先となりログ飛びが起こります。

Scripting.FileSystemObjectのOpenTextFileを使用し、
IOMode ForAppending=8でファイルストリームを開き、
行末追加を行うことで対策できます(社用ログはそれで行っている)

 o_Fs = CreateOleObj("Scripting.FileSystemObject")
 o_ts = o_Fs.OpenTextFile(_Path, _IOMode, TRUE)
 o_ts.WriteLine(_Log)
 o_ts.Close()

例外処理等いろいろ省いてますので自身で試行錯誤してください。

No.1212 2021/02/20(Sat) 09:15:03

Re: FCLOSE関数の引数をTRUEにした場合のデメリット / takahi
しろまささん有難うございます。
Scripting.FileSystemObjectとても良いですね。
わざわざ毎回CloseしなくてもWriteLine(_Log)した時点で書き込んでくれるので
とても早いし、読み込みとぶつかることもありません。

今のところ全て正常終了なので例外処理が分かりませんでしたが、これから色々調べます。

No.1213 2021/02/20(Sat) 15:12:32
エラー / あんき
リンクボタンを押すと以下のエラーが出るのですが、意味を辞書で引いてもわかりません、何か対処の仕方ございますでしょうか。
for-next could not convert variant of type (dispatch)into type (oleStr)
for elem in obj.document.GetElementsBY TagName("input")

No.1203 2021/02/18(Thu) 18:05:17

Re: エラー / Rayna
>>1203 あんき さん
 Dispatch型(オブジェクト)からoleStr型に型変換失敗してますね
 Dispatch型に For-In 出来るコレクションがないだけだとメンバーが見つかりませんとでるので
 obj.document.getElementsByTagName("input") に NOTHING が返ってるとかですかね

 渡そうとしてるオブジェクトをPrintするなりして内容を確認してみてください

No.1204 2021/02/18(Thu) 18:39:37

Re: エラー / stuncloud
> GetElementsBY TagName
ここの半スペのせい?かも?
(通常なら文字列にする処理が不要な気がするので)

No.1206 2021/02/18(Thu) 20:02:24
反応がない / sousou
お世話になります。
以下、簡単なものなのに、ボタンを押しても反応が遅い、反応しない場合(ダブルクリックなど)があります、多くのボタンがある場合、必ず反応しないと誤動作になります、一瞬でも押したら、必ず反応させる方法はありますでしょうか。
最低でも1つのボタンは、確実にダブルクリックでも2回表示させたいのです。

obj = CREATEFORM("about:blank", "Calc", True, FOM_NOHIDE) 
obj.Document.write(計算フォーム)      
while obj.Visible              
  if GETFORMDATA("CalBtn1") then print "1" 
  if GETFORMDATA("CalBtn2") then print "2" 
wend

TextBlock 計算フォーム  
 <form method='POST'>        
<input type='submit' value=' 計算1 ' name='CalBtn1'>

<input type='submit' value=' 計算2 ' name='CalBtn2'>

 </form>
EndTextBlock

No.1199 2021/02/18(Thu) 10:48:06

Re: 反応がない / stuncloud
oleeventを使います
oleeventによりボタンがクリックされた際に任意の関数を実行できます

-------
obj = CREATEFORM("about:blank", "Calc", True, FOM_NOHIDE)
obj.Document.write(計算フォーム)

// クリック時のイベントハンドラを指定
// ここではすべてのinput要素に対して指定を行う
for elem in obj.document.GetElementsByTagName("input")
 oleevent(elem, "HTMLInputTextElementEvents2", "onclick", "onclick")
 oleevent(elem, "HTMLInputTextElementEvents2", "ondblclick", "onclick")
next

while obj.Visible
 sleep(0.1)
wend

TextBlock 計算フォーム  
 <form method='POST'>        
<input type='submit' value=' 計算1 ' name='CalBtn1'>

<input type='submit' value=' 計算2 ' name='CalBtn2'>

 </form>
EndTextBlock

// ボタンクリック時に呼び出される関数
procedure onclick()
 select EVENT_PRM[0].srcElement.name // イベント元になるエレメントのnameにより処理を分岐
  case "CalBtn1"
   print 1
  case "CalBtn2"
   print 2
 selend
fend
-------

oleeventを2回呼んでる理由は
・onclickだけだとダブルクリック時の2回目のクリックを取りこぼす
・ondblclickでダブルクリック時のイベントを拾えるので取りこぼしをカバーできる
からです

No.1200 2021/02/18(Thu) 11:54:45

Re: 反応がない / sousou
stuncloud様ありがとうございます、oleeventの使い方研究します。
No.1202 2021/02/18(Thu) 15:18:23
オブジェクトの状態取得 / あかは
会社で使っているソフトに ファンクションバー というのがあります。
ファンクションバーの表示状態を確認したいのですが、ファンクションバーはカスタマイズ可能なので、できれば画像判定以外で確認したいと思ったのですが、行き詰まってしまいました。

とりあえず getid(get_frompoint_obj) でIDを取得して st_title と st_class を確認したところタイトルは無しで、クラスはBCGPControlBar:40000000:8:10003:10でしたので、これでIDを取得してst_visibleで確認しようかと思いまして、

getid("","BCGPControlBar:40000000:8:10003:10")を試しましたが-1が返ってくるので見つからないのだと思います。
(まあ本来ウィンドウのIDを返す関数らしいので、当然なのでしょうが)

なにか良い手段がありましたらご教授お願いします。

No.1195 2021/02/17(Wed) 14:03:57

Re: オブジェクトの状態取得 / stuncloud
そのファンクションバーのあるウィンドウのIDをgetidで取得し

bFunctionBar = false
for cid in getallwin(id)
 if pos("BCGPControlBar", status(cid, ST_CLASS)) > 1 and status(cid, ST_TITLE) = "" then
  bbFunctionBar = true
  break
 endif
fend

if bFunctionBar then
 msgbox("ファンクションバーがありました")
else
 msgbox("ファンクションバーはありませんでした")
endif

みたいなことができるかもしれません
これは BCGPControlBar から始まるクラス名を持つ子ウィンドウが他にない場合に有効です
なんなら BCGPControlBar:40000000:8:10003:10 をposに渡してもいいかもしれませんが
後ろの数値のあたりが一意かどうかあやしい (起動する度に変化するということもあるかも?) ので
このような書き方にしてみました
> getid("","BCGPControlBar:40000000:8:10003:10")
が-1だったということもありますし

あとそもそもの話で getid(get_frompoint_obj) したものが本当にファンクションバーかも疑わねばなりません
(実は見えてるもののIDじゃなかったということがよくあるので…)
なので getallwin(id) で子ウィンドウ一覧が取れるようであれば、ファンクションバーの有無でその状態を確認する
という作業が必要になるかもしれません

for cid in getallwin(id)
 print status(cid, ST_CLASS) // クラス名調査用
 print status(cid, ST_VISIBLE) // 可視かどうか (ファンクションバーがなくても子ウィンドウとしては存在してて見えてないだけ、かどうかの確認)
 print status(cid, ST_CLX) // クライアント座標を確認することでおおよそどのへんにあるかわかる
 print status(cid, ST_CLY) // 同上
fend

など必要に応じてstatus()していく

No.1196 2021/02/17(Wed) 15:52:25

Re: オブジェクトの状態取得 / Rayna
>>1195 あかは さん
 子ウインドウを獲得する場合は
 GetCtlHnd か GetAllWinの子ウインドウ列挙 を使います
 親ウインドウIDが取れてれば獲得できるはず...

 うまく行かない場合は GET_FROMPOINT_OBJ で得たIDの ST_PARENT を
 辿っていくとどれが親かわかりやすいです


//| 追記(2021/02/18) |//////////
// 上げるほどのことでもないので追記
// GetCtlHnd の戻値ですが割と組込関数でなんとかなっちゃいます

 Dim idWnd = GetId(GET_ACTIVE_WIN) // = GetId([Window Title], [Window Class])
 While idWnd=GetId(GET_ACTIVE_WIN)
  Sleep(0.1)
 WEnd
 idWnd = GetId(GET_ACTIVE_WIN)
 Dim idWndCtl = HndToId(GetCtlHnd(idWnd, "BCGPControlBar:40000000:8:10003:10"))
 IfB GetId(GET_ACTIVE_WIN)=idWnd Then
  IfB Status(idWndCtl, ST_VISIBLE)=TRUE Then
   Print GetWinNameStrs(idWndCtl)+" は表示状態"
  ElseIf Status(idWnd, ST_ISID)=FALSE Then
   Print "親が獲得できてないか閉じられている"
  ElseIf Status(idWndCtl, ST_ISID)=FALSE Then
   Print "子が獲得できてないか閉じられている"
  Else
   Print GetWinNameStrs(idWndCtl)+" は非表示状態"
  EndIf
 EndIf
 Print

 PutChildWindowTree(idWnd) // ウインドウ親子関係一覧出力
 While Status(GetId(GET_LOGPRINT_WIN),ST_VISIBLE);Sleep(0.7);WEnd
 Procedure PutChildWindowTree(idWnd, nIndent=0)
  Dim idWndCtl, sIndent=Format(" ", (nIndent+1)*2)
  If nIndent=0 Then Print GetWinNameStrs(idWnd)+" の子ウインドウ一覧"
  For idWndCtl In GetAllWin(idWnd)
   If Status(idWndCtl, ST_PARENT)<>idWnd Then Continue
   Print sIndent+GetWinNameStrs(idWndCtl)
   PutChildWindowTree(idWndCtl, nIndent+1)
  Next
 FEnd
 Function GetWinNameStrs(idWnd)
  RESULT = "[<#DBL>"+Status(idWnd,ST_TITLE)+"<#DBL>, <#DBL>"+Status(idWnd,ST_CLASS)+"<#DBL>]"
  RESULT = Replace(RESULT, "<#CR>", "<CR>") // Editコントロールとかでテキストが ST_TITLE になってるの対策
 FEnd

No.1197 2021/02/17(Wed) 16:01:07

Re: オブジェクトの状態取得 / しろまさ
// GetCtlHnd例(VncViewer例 要変更)

//ウィンドウIDの取得
  id_W = GetID("New TightVNC Connection", "#32770", 0.2)
  hndW = GetCtlHND(id_W, "Button", 2)
// hndW = GetCtlHND(id_W, "BCGPControlBar:40000000:8:10003:10", 1)

//objClass[ Button ]の取得と設定
  o_Text = objText(hndW)  // 取得 o_Text= "&Connect"
  MsgBox(o_Text)
  objText(hndW, "asd")  // 設定
// objText(hndW, "asd", TRUE)  // 設定(入力確認付)

Function  objText(hndW, a_SetText = NULL, a_ChkText = FALSE)
  Result  = ""
  Dim Buff  = Format(ChrB(0), $FF), tBuff
  Ifb  a_SetText <> NULL
    SendMessageA(hndW, WM_SETTEXT, 0, a_SetText)
    Ifb a_ChkText
      Repeat
        tBuff  = Buff
        SendMessageA(hndW, WM_GETTEXT, $FF, tBuff)
      Until  Trim(tBuff) = a_SetText
    EndIf
  Else
    If  SendMessageA(hndW, WM_GETTEXT, $FF, Buff) > 0  Then Result  = Trim(Buff)
  EndIf
FEnd
DEF_DLL  SendMessageA(HWND, UINT, LONG, var PCHAR) :LONG :user32.DLL
  Const  WM_SETTEXT  = $000C
  Const  WM_GETTEXT  = $000D

No.1198 2021/02/17(Wed) 16:57:14

Re: オブジェクトの状態取得 / あかは
みなさんありがとうございます。

ウィンドウにくっついているオブジェクトも、ウィンドウという扱いで良いのですね。
とりあえず getallwin()で子ウィンドウを数えたところ、60もあるので
>>1196
を参考に

wID = getid(,"Afx")
for cID in getallwin(wID)
if pos("BCGPControlBar",status(cID, st_class)) then print "★★★★"
print "cID("+ cID + ") = " + status(cID, st_class)
print status(cID, st_visible)
print "X= " + status(cID, st_clx) + ", Y= " + status(cID, ST_CLY)
print "W= " + status(cID, st_clwidth) + ", H= " + status(cID, st_clheight) + "<#CR>"
next

とスクリプトを書いて実行したところ、表示状態の違いで

★★★★
cID(37)= BCGPControlBar:40000000:8:10003:10
True
X= 0, Y= 1033
W= 1920, H= 22

★★★★
cID(19)= BCGPControlBar:40000000:8:10003:10
False
X= 0, Y= 24
W= 318, H= 223

とそれぞれ確認できました。

親ウィンドウの st_title は 業務毎に異なり、st_class は Afx〇〇(〇〇は変動する)でかつ、別の作業で立ち上げているウインドウもクラスが Afx〇〇(しかもそれぞれのウィンドウにファンクションバーがあり、表示状態が異なる)
なので、一意の値での特定が困難なのですが、アクティブウィンドウを対象にする事でなんとかできそうです。(お茶を濁すとも言う)

No.1201 2021/02/18(Thu) 11:59:48
このエラーはなんでしょうか? / 太郎
おせわになります。
毎朝モニターを入れるだけの簡単なプログラムなのですが
今朝下記のようなエラーのポップアップがでておりました。
このエラーは一体何なのでしょうか?
external exception c0000006

No.1193 2021/02/17(Wed) 09:31:43

Re: このエラーはなんでしょうか? / stuncloud
このへんですかねぇ
https://stackoverflow.com/questions/1317886/external-exception-c0000006
これはアプリケーション自身が取り外し可能なディスクに置いてあり、自身を実行中にそのディスクを取り外すとこのエラーが発生するという話、ですかね
プログラム全部をメモリにロードするようにして回避しなされ、ということみたいですね

ほかにも検索するといろいろ出てくるんですが、以下であれば
https://wiki.agencysystems.com/wiki/Error:_External_Exception_C0000006
アプリケーションが共有フォルダに置かれていて途中でそこへのアクセスが失われるとこのエラーが出るという話っぽいです

要するに途中でUWSC.EXEかあるいは必要なDLLだとかにアクセスできなくなってる?ということでしょうかね?

なので

UWSC自身、スクリプト、またはその両方が共有フォルダに置いてあるのであればローカルに置いてみる
いずれもローカルにあるのにこの現象が発生するならファイルIOがおかしくなってるかもしれないのでCHKDSKなどによる診断や修復を試みる
それでもどうにもならないならストレージを交換する

といった対処法がもしかしたら有効かもしれません
エラーが頻発するようでしたらお試しください

No.1194 2021/02/17(Wed) 11:07:17
GETKEYSTATEについて / あかは
手元に getkeystate(3) で [Ctrl] + [Pause/Break] を検出するスクリプトがあるのですが、この3が何処から出てきたのか、どういった数字なのか、ネットを検索してもさっぱり分かりません。
何方か御存知ないでしょうか。

No.1190 2021/02/15(Mon) 14:42:48

Re: GETKEYSTATEについて / Rayna
>>1190 あかは さん
 ヘルプに書かれていないキーコードは以下が参考になると思います
 ttps://docs.microsoft.com/ja-jp/windows/win32/inputdev/virtual-key-codes
 ttp://kts.sakaiweb.com/virtualkeycodes.html


//| 追記(2021/02/15) |//////////
>>1192
 UWSCの内部で扱われているAPIの定数ですね
 そのうちのよく使う定数だけをピックアップして
 わかりやすく(例えば VK_LWIN -> VK_WIN みたいな)再定義したものが
 UWSCのヘルプに書かれている VK_* の定数です

No.1191 2021/02/15(Mon) 15:30:17

Re: GETKEYSTATEについて / あかは
仮想キーコード一覧が大変参考になりました、ありがとうございました。
プログラムはさっぱりなのですが、これは、UWSCが規定している数値?ではないんですね、探しても解らなかった訳です。

No.1192 2021/02/15(Mon) 15:48:30
数値の桁数をそろえたい / かーくん
1〜9は0001〜0009の文字列
10〜99は0010〜0099
100〜999は0100〜0999
1000〜9999はそのまま
を一行でする方法はありますか?

桁数を調べてif文を使うと何行にもなってしまうし
format関数でやろうとしましたが、上手く行きませんでした。
format("000" + x ,3)

No.1182 2021/02/14(Sun) 03:28:36

Re: 数値の桁数をそろえたい / satocha
確かにformat関数の動きがおかしいですね。
仕方ないので
replace(format(x,4)," ","0")
でどうでしょうか。

No.1183 2021/02/14(Sun) 04:10:31

Re: 数値の桁数をそろえたい / かーくん
satocha さん、有難うございます。
Formatで左にできたスペースを「0」に変える方法、思いつきませんでした。
これだと他の事にも応用できそうです。
 

No.1184 2021/02/14(Sun) 04:53:32

Re: 数値の桁数をそろえたい / Rayna
>>1182 かーくん さん

Dim i, x
// "000"+x で文字列型になるので
// 文字列型の前方繰り返し処理になってますね
For x In Split("1 11 111 1111", " ", FALSE, TRUE)
 Print VarType(x)=VAR_DOUBLE // True // この時点では数値型(Double型)
 Print VarType("000"+x)=VAR_USTR // True // この時点で文字列型(UStr型)にキャストされる
 Print Format("000"+x, 3)
Next

// つまり以下と同じ動作です
For i = 0 To 9
 Print "i="+i+":"+Format("string", i)
Next

// 正しくは以下の2パターン、場合によって使い分けると便利です
For x In Split("1 11 111 1111", " ", FALSE, TRUE)
 // 数値型として半角スペースで埋めて置き換え // >>1183 satocha さんの方法
 Print Replace(Format(x, 4), " ", "0")
 // 必要文字数からx文字数を引いて文字列"0"を繰り返し + x
 Print Format("0", 4-Length(x)) + x
Next

// 前者は16進数で処理するときにも対応 // デメリット:数値以外繰り返し処理, 左詰めができない
 Print Replace(Format($FF, 4, -1), " ", "0") // "00FF"
 Print Replace(Format("abc", 4, -1), " ", "0") // "abca"

// 後者は数値に限らず半角文字列に対応 // デメリット:変数を用意しないと冗長, 16進数が面倒
 x = $FF // 255
 Print Format("0", 4-Length(x)) + x // "0255"
 x = Format($FF, 0, -1) // こうすれば16進数も対応
 Print Format("0", 4-Length(x)) + x // "00FF"
 x = "abc" // 文字列
 Print Format(".", 4-Length(x)) + x // ".abc"
 x = "あ" // 全角文字列が入ってる場合はLengthBを使う(埋め文字が半角の場合のみ有効)
 Print Format(".", 4-LengthB(x)) + x // "..あ" // 右詰め
 Print x + Format(".", 4-LengthB(x)) // "あ.." // 左詰め

No.1185 2021/02/14(Sun) 10:51:06

Re: 数値の桁数をそろえたい / かーくん
Raynaさん有難うございます。
加える「0」の文字列を作って、xの左に加える方法なるほどです。
また、文字列だった場合の方法も教えて頂きありがとうございました。

No.1186 2021/02/14(Sun) 13:24:07

Re: 数値の桁数をそろえたい / しろまさ
// シンプルにこんな方法もあります。
Dim n = 99
MsgBox( Copy("000"+n, Length(n)) )

No.1189 2021/02/15(Mon) 13:11:40
多次元の連想配列の値を更新したい / cho
内容がタイトルと相違してきたので、別スレッドにしました。
No.1177 2021/02/13(Sat) 16:42:51 からの続きです。

通常の多次元と同じ書き方でSyntaxErrorが出ます。
たぶん、とても簡単なことだと思うのですが・・・


DIM v[1][1]

v[0][0] = "value" // 通常の2次元はこの書き方で代入できる
PRINT v[0][0]

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
print h["hoge"][0]

// やってみた書き方(他言語の書き方も参考してみましたが全滅でした)
 // h["hoge"] = 0."f002"
 // h["hoge",0] = "f002"
 // h = ["hoge",[0] = "f002"]
 // h = ["hoge","f002"]
 // h = ["hoge"]["f002"]
 // h["hoge"] = 0."f002"
 // h["hoge"] = 0:"f002"
 // h["hoge"] = [0]:"f002"
 // $h["hoge"][0] = "f002"
 // h["hoge"]["0"] = "f002"
 // h["hoge"][0] = $"f002"
 // h["hoge"] = [0,"f002"]
 // h["hoge"] = [0]"f002"
 // h["hoge"[0]] = "f002"
 // h["hoge",0] = "f002"
 // h["hoge"][0] = h["hoge"]["f002"]
 // h["hoge"][0] = {"f002",,}

// あれから粘ってやってみましたが、自己解決に至りませんでした。
// 値の更新はとりあえず、置換などの後ろ向きな解決法が使えたので困ることはないと思います。
// それでも、連想の多次元を使えることを知れたのは幸運でした。ありがとうございます。
// 時間に余裕が出たら再チャレンジしてみます。

//苦肉の策。置換してSafeArrayで丸ごと更新
value = h["hoge"][0]
str = JOIN(h["hoge"])
h["hoge"] = SPLIT(REPLACE(str,value,"f003")) //値が重複する場合もあるので、カウントもする処理も追加する

print h["hoge"][0]

No.1180 2021/02/13(Sat) 19:13:41

Re: 多次元の連想配列の値を更新したい / cho
時間的にすれ違ったので、転載します。

>>  ☆ Re: EVALで値の代入したい NEW / stuncloud 引用
>> > h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
>> うわあ、確認不足でしたごめんなさい
>> これはおそらく連想配列の要素にインデックス指定して代入、をUWSCが許容していないということだと思います
>> 値を読むだけならOKだけど代入は無理ということになりますね
>> つまりこの方法は使えない…ので忘れてください…ほんとすいません…
>> 
>> > COMオブジェを経由して使える連想配列という認識
>> そんな感じでOKです
>> 例えば連想配列を関数の戻り値にしたいけど、仕様上できないので代わりにScripting.Dictionaryを使う
>> みたいな感じで使うことがあったりなかったりします



stuncloudさんレスありがとうございます。

なるほど、仕様上できないのですね。
SyntaxError = 構文エラーなので、書き方があるのかと思いました。
わかってスッキリしました。

実は、先日の質問内容(moduleと2次元で解決できると考えた)ですが、
「適当な数字」の桁数が多かった(JANコードみたいなものです)ため、2次元配列に入れることが出来なく、解決策を考えていました。
適当な数字をなぜキーにしていたのか、うっかり忘れていました。
そこに、Scripting.Dictionaryのお話をいただけて、
もしかしたら出来るかも。という気持ちになっています。

話に出たのは偶然だったかもですが、新しいヒントをありがとうございます。
頑張ってみます。

No.1181 2021/02/13(Sat) 19:47:29

Re: 多次元の連想配列の値を更新したい / しゅん
// こんな感じ?

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

SetHash(h, "hoge", 0, "f002")
print h["hoge"][0]


PROCEDURE SetHash(var h[], key, index, value)
  DIM sa = h[key]
  sa[index] = value
  h[key] = sa
FEND

No.1187 2021/02/15(Mon) 07:54:57

Re: 多次元の連想配列の値を更新したい / cho
しゅんさんありがとうございます。

まさしくやりたいことが実現できます。
値の重複を気にすることなく、ダイレクトに更新できる点がとてもスマートだと思いました。
その自作関数丸ごと使わせていただきます。感謝。

このスレを参考にされる方が他にもいるかもしれないので、
私が確認用に使ったコードを載せておきます。
連想配列を多次元・可変長で使う方の参考になれば幸いです。

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
h["fuga"] = SPLIT("apple orange melon mango banana kiwi")
// print h["hoge"][0] // foo

SetHash(h, "hoge", 0, "f002")
// print h["hoge"][0]
SetHash(h, "fuga", 4, "GoBananas")

// 確認用
FOR i = 0 TO LENGTH(h)-1
 key = h[i,HASH_KEY]
 FOR j = 0 TO LENGTH(h[key])-1
   PRINT key+"["+j+"] = "+h[key][j]
 NEXT
NEXT

PROCEDURE SetHash(var h[], key, index, value)
  DIM sa = h[key]
  sa[index] = value
  h[key] = sa
FEND

// bananaをGoBananasに変えて洒落を利かせてみました(笑)

No.1188 2021/02/15(Mon) 11:31:07
EVALで値の代入したい / cho
お世話になります。
表題の件ですが、行き詰っているので解決できるヒントがあればお願いします。

HASHTBL Apple
HASHTBL Orange
HASHTBL Melon

TEXTBLOCK list_fruit
Apple
Orange
Melon
ENDTEXTBLOCK

DIM fruit_list[3]
Array = SPLIT(list_fruit,"<#CR>")
FOR i=0 TO LENGTH(Array)-1
  fruit_list[i] = Array[i]
  PRINT "fruit_list["+i+"] = "+fruit_list[i] // 確認用
NEXT

fruit_Number = "100" //適当な数字
Apple[fruit_Number] = "ふじ"
PRINT Apple[fruit_Number] // = ふじ と表示される
PRINT EVAL(fruit_list[0]+"[fruit_Number]") // = ふじ と表示される

// やりたいこと
  // EVAL(fruit_list[0]+"[fruit_Number]") = "紅玉" //代入して値を更新したい。ここでエラーが出る
  // PRINT EVAL(fruit_list[0]+"[fruit_Number]") // 紅玉 と表示させたい
// 試したこと(EVALは代入に:=を使うらしい)
  // ()の位置や""で囲む位置などを工夫したがエラーになる
  // EVALの重ね掛けを試してみるなど迷走中・・・
  // EVAL(EVAL(fruit_list[0]+"[fruit_Number]"):="紅玉")
  // EVAL(EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>") //エラーはでないが代入されない
// 希望の条件
  // 自作関数の引数にfruit_list[]を使ってFORで回したい
  // PUBLICは使いたくない

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

No.1162 2021/02/11(Thu) 01:32:40

Re: EVALで値の代入したい / しゅん
// おしいですね!
EVAL(fruit_list[0]+"[fruit_Number] := <#DBL>紅玉<#DBL>") //代入して値を更新できます!
PRINT EVAL(fruit_list[0]+"[fruit_Number]") // 紅玉 と表示されます!

No.1163 2021/02/11(Thu) 09:04:21

Re: EVALで値の代入したい / Rayna
>>1162 cho さん

代入できてない場合は以下に気をつけてみてください
 代入しようとした変数が間違っている
  Eval した関数のローカル変数として作成しようとするので
  代入先ではなく新変数に入ってる可能性があります
 Evalを使用した, モジュール、関数内、関数外に同名の変数がある
  Eval は変数を外向きに探索するので 場合によっては Global. This. 等を明示しないと駄目な場合があります

これを意識しながら書くと失敗しにくいと思います
分かりづらいなら Eval しようとしてる文字列を一度 Print してみてください

以下を例にあげると
>>  // EVAL(EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>") //エラーはでないが代入されない
 Print EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>" // "ふじ:=<#DBL>紅玉<#DBL>"
 EVAL(EVAL(fruit_list[0]+"[fruit_Number]")+":=<#DBL>紅玉<#DBL>")
 Print Eval(fruit_list[0]+"[fruit_Number]") // ふじ と表示される
 Print Eval("ふじ") // 紅玉 と表示される
新規変数 ふじ に代入してますね

>>  // 自作関数の引数にfruit_list[]を使ってFORで回したい
Function f(fruit_list[])
 [] をつけると 変数, 配列, 連想配列 を引数として受けることが出来ます

No.1164 2021/02/11(Thu) 09:45:56

Re: EVALで値の代入したい / しゅん
// Raynaさん、丁寧なフォロー、ありがとうございます。
// よくよく考えると、EVAL使うのが間違いな気がしてきました。


HASHTBL Fruits

TEXTBLOCK list_fruit
Apple
Orange
Melon
ENDTEXTBLOCK

DIM fruit_list[3]
Array = SPLIT(list_fruit,"<#CR>")
FOR i=0 TO LENGTH(Array)-1
  fruit_list[i] = Array[i]
  PRINT "fruit_list["+i+"] = "+fruit_list[i] // 確認用
NEXT

fruit_Number = "100" //適当な数字
Fruits[GetIdx("Apple", fruit_Number)] = "ふじ"
PRINT Fruits[GetIdx(fruit_list[0], fruit_Number)] // ふじ と表示される
Fruits[GetIdx(fruit_list[0], fruit_Number)] = "紅玉"
PRINT Fruits[GetIdx(fruit_list[0], fruit_Number)] // 紅玉 と表示される



FUNCTION GetIdx(kind, index)
  RESULT = kind + CHR(0) + index // 絶対に使わない文字を区切り文字にする
FEND

No.1165 2021/02/11(Thu) 10:50:48

Re: EVALで値の代入したい / cho
しゅんさんありがとうございます。

EVAL(fruit_list[0]+"[fruit_Number] := <#DBL>紅玉<#DBL>")
この囲み方、覚えておきます。ホント惜しかった。でも重ね掛けに視点が移っていたので、気が付くのに時間がかかったか、あきらめていたかもです。助かりました。

Raynaさんありがとうございます。

いただいたコードを実行してみました。
ふじ という変数に紅玉が入っているのを確認しました。
外向きに探索という表現は初耳でわかりませんでしたが、調べてみます。
盲点になりそうな点を教えていただきありがとうございます。

EVALで代入できることがわかったので、幅が広がりそうです。
本当にやりたいことは、20個程度ある連想を、PUBLICを使わずに自作関数を通して更新していくことです。

と、返信を書いている間に、しゅんさんからそれらしい追加アイデアが!
さっそく試してみます。
取り急ぎ、お礼まで。

No.1166 2021/02/11(Thu) 11:21:21

Re: EVALで値の代入したい / Rayna
>>1166 cho さん

>> 外向きに探索という表現は初耳でわかりませんでしたが、調べてみます。

分かりづらかったかもしれないので補足
Eval に限った話ではないですが
UWSC では スクリプト、モジュール、関数に参照できる範囲があり 同名の 関数名, 変数名 をつけることが出来ます

Const, TextBlock, Public, Public HashTbl, Def_Dll, Procedure, Function がグローバル参照で
Dim, HashTbl はローカル参照です

Module m の Procedure p 内で 変数 m.v を呼ぼうとして Eval("v") とかすると
m.p() 内に 変数 v がなければ成功しますが あった場合 m.p() 内の v が優先されます
それを回避する為に明示しないと駄目な場合があるよって話でした

詳しくはプログラミングにおけるスコープという概念を調べてください
どこからならどの変数を参照できるか等確かめてみてもいいかもしれません

//| サンプル |//////////

Public vp = "スクリプトのグローバル変数"
Dim v = "スクリプトのローカル変数"

m.p()

Procedure p()
 Dim v = "モジュール外関数のローカル変数"
FEnd

Module m
 Public vp = "モジュールのグローバル変数"
 Dim v = "モジュールのローカル変数"
 Procedure p()
  // 変数は Global が使えない
  Dim v = "モジュール内関数のローカル変数"
  Print v // Eval("v")
  Print This.v // Eval("This.v")
 FEnd

 Procedure p2()
  p() // m.p()
  m.p() // m.p()
  This.p() // m.p()
  Global.p() // p()
 FEnd
EndModule

No.1167 2021/02/11(Thu) 13:00:39

Re: EVALで値の代入したい / cho
しゅんさんありがとうございます。
残念ながら、私の力量では希望の処理をさせることができませんでした。
Fruits[GetIdx(fruit_list[0], fruit_Number)] = "紅玉"
しかし、このような形で、配列に関数を書くことができることを学びました。
アドバイスありがとうございます。

今一度、やりたいことを整理したので、何か良いヒントがあればお願いします。
EVALは使ったことがなく、苦肉の策でしたのでこだわりはありません。
やりたいことは、たぶん仕様的に無理かもしれないと考えていますが、
最悪、連想を宣言した関数内でFORをさせることは出来そうです。
同じ処理が何度か出てくるのでそのたびに書くと無駄にコードが長くなるので
少しでも見やすくできればと考えています。


HASHTBL Apple // 連想配列が20個程度ある
HASHTBL Orange
HASHTBL Melon

TEXTBLOCK list_fruit
Apple
Orange
Melon
ENDTEXTBLOCK

DIM fruit_list[3]
Array = SPLIT(list_fruit,"<#CR>")
FOR i=0 TO LENGTH(Array)-1
  fruit_list[i] = Array[i]
  PRINT "fruit_list["+i+"] = "+fruit_list[i] // 確認用
NEXT

fruit_Number = "100" //適当な数字
Apple[fruit_Number] = "ふじ"
Orange[fruit_Number] = "甘夏"
PRINT Apple[fruit_Number] // = ふじ と表示される
PRINT Orange[fruit_Number] // = 甘夏 と表示される

// この部分を別関数にしてFORで回したい(fruit_Numberは固定です) ////////
  EVAL(fruit_list[0]+"[fruit_Number] := <#DBL>つがる<#DBL>")
  EVAL(fruit_list[1]+"[fruit_Number] := <#DBL>清見<#DBL>")
///////////////////////////////////

PRINT Apple[fruit_Number] // = つがる と表示される
PRINT Orange[fruit_Number] // = 清見 と表示される

//処理ここまで

  //自作関数の処理 ※イメージなので動作しません
   // 連想を引数にすると解決できますが、20個ぐらい書くので、リスト化したものでシンプルにしたい
   // 連想をPUBLICするとこの問題は解決できますが、PUBLICしたくない
  PROCEDURE value_Update(Var fruit_list[],fruit_Number)
   // New_valueは外部データから取得するため、この関数内のコードは少し長くなります。
   FOR i=0 TO LENGTH(fruit_list)-1
    EVAL(fruit_list[i]+"[fruit_Number] := New_value")
   NEXT
  FEND

// 何かアイデアやヒントがあればぜひお願いします。

No.1168 2021/02/11(Thu) 13:28:08

Re: EVALで値の代入したい / cho
Raynaさんありがとうございます。

サンプルを動かして、コードの流れと結果を見比べてみました。
まだ、Evalの振る舞い(?)を理解できていませんが、

MODULEを使った場合のスコープについては理解が進んだような気がします。
特に、今回のヒントで、
「連想をPUBLICしたくないけど、別関数の処理結果で値を変えたい」というわがままは、
連想を宣言した処理をまるごとMODULEで括ってしまえば、
MODULE内で、PUBLICを宣言することで解決できそうな気がしています。

今から、仕事で少し外出してきますが、帰宅後色々試してみます。
スコープという視点、貴重なヒントになりました。ありがとうございます。

No.1169 2021/02/11(Thu) 13:55:13

Re: EVALで値の代入したい / stuncloud
連想配列ではなく二次元配列を使うという案

const lists = 3 // リストの数 (20個あるなら20)
const items = 200 // 最大アイテム数

// リスト一覧 ※ 必ず連番にしていく
const Apple = 0
const Orange = 1
const Melon = 2

dim fruit_list[lists - 1][items - 1]


fruit_Number = 100

fruit_list[Apple][fruit_Number] = "ふじ"
fruit_list[Orange][fruit_Number] = "甘夏"

print fruit_list[Apple][fruit_Number]
print fruit_list[Orange][fruit_Number]

procedure value_Update(var fruit_list[], fruit_Number)
 for i = 0 to length(fruit_list) - 1
  New_value = New_value取得処理()
  fruit_list[i][fruit_Number] = New_value
 next
fend


fruit_list[Apple][0] みたいな書き方ができるので区別はしやすいかな?という感じでやっています
evalも使いませんし
ただ、そのためのcosnt定義でうっかりするとバグになっちゃうしあまり良い解決案ではないですね

# enum欲しくなりますね

No.1170 2021/02/11(Thu) 14:07:43

Re: EVALで値の代入したい / cho
stuncloudさんありがとうございます。

希望通りの処理ができました。
2次元配列が呼出時に連想配列と同じ書き方ができるというのも、私にはとても新鮮な使いかたで感動しました。
cosntを超えるとバグるかもしれないという点も考慮してitemsを調整してみます。

全体処理に組み込んだ時に希望通りの動作をしてくれるように頑張ります。

しゅんさん、 Raynaさん、stuncloudさん改めてありがとうございます。
いただいたアイデアやヒントはどれも、今後に役立たせていけそうです。

なるべく自分で解決する努力をしますが、行き詰った時にアドバイスを求めるかもしれません。
また見かけた時は何卒よろしくお願いします。

No.1171 2021/02/12(Fri) 07:40:04

Re: EVALで値の代入したい / しゅん
// もう不要かもしれませんが、こんな感じ?


HASHTBL Fruits // 連想配列はこれ一つでOKです。CONST/fruit_listを20個作ってください

// Const良いですね。この方式の場合、ユニークなら連番でなくても良いです。
Const Apple = 100
Const Orange = 200
Const Melon = 300
DIM fruit_list[] = Apple, Orange, Melon

fruit_Number = "100" //適当な数字
Fruits[_I(Apple, fruit_Number)] = "ふじ" // Apple[fruit_Number]をこう書き換えます。以下同じ
Fruits[_I(Orange, fruit_Number)] = "甘夏"
PRINT Fruits[_I(Apple, fruit_Number)] // = ふじ と表示される
PRINT Fruits[_I(Orange, fruit_Number)] // = 甘夏 と表示される

value_Update(Fruits, fruit_list, fruit_Number)

PRINT Fruits[_I(Apple, fruit_Number)] // = つがる と表示される
PRINT Fruits[_I(Orange, fruit_Number)] // = 清見 と表示される



FUNCTION _I(kind, index) // GetIdxは入力が面倒なので変えました
  RESULT = kind + CHR(0) + index // 絶対に使わない文字を区切り文字にする
FEND


TEXTBLOCK list_data
紅玉
清見
マスクメロン
つがる
ENDTEXTBLOCK

PROCEDURE value_Update(var fruits[], fruit_list[], fruit_Number) // fuit_listは参照のみなのでvar不要
 DIM datas = SPLIT(list_data, "<#CR>")
 FOR i=0 TO LENGTH(datas)-1
  fruits[_I(fruit_list[i Mod 3], fruit_Number)] = datas[i]
 NEXT
FEND

No.1173 2021/02/12(Fri) 12:10:56

Re: EVALで値の代入したい / cho
しゅんさん気にかけていただいてありがとうございます。

コード拝見させていただきました。

連想配列を一つにすることで参照渡しで更新できるのはとても便利だと感じました。

連想配列を多次元(例:連想名[キー][][]][]など)にできないかと数日間悩んでいたのを憶えています。
この書き方を使えるようになれば、いろんな問題が解決できそうです。

今回はMODULEと2次元配列で私の問題を解決できそうですが、
誰か(未来の私かもしれない)の参考になると思います。
素晴らしいヒントとコードをありがとうございます。

No.1175 2021/02/12(Fri) 17:50:06

Re: EVALで値の代入したい / stuncloud
> 連想配列を多次元
SafeArrayを使えば連想配列で個別に配列を持たせることも可能です

hashtbl h

h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

h["fuga"] = safearray(0, 9) // 長さ10の空の配列
h["piyo"] = safearray(0, 9, 0, 2) // 二次元配列もできる

さらにさらに
変数に連想配列のようにキーと値のペアを保持できるものを代入したい、という場合はScripting.Dictionaryが使えます
(値の出し入れがメソッド経由になるのでちょっと書くのが手間になりますが、なかなか便利です)

h["d"] = createoleobj("Scripting.Dictionary")
h["d"].Add("foo", "FOO") // foo というキーに対して FOO という値をセット
print h["d"].Item("foo") // FOO

No.1176 2021/02/13(Sat) 11:31:46

Re: EVALで値の代入したい / cho
stuncloudさんありがとうございます。

連想配列も多次元にできるのですね。
配列を勉強していた時に、とあるブログで
・連想配列は多次元配列では使えないのでありません。
という一文を読んで、鵜呑みにしていました。お恥ずかしいです。

SafeArrayは戻り値を配列で受ける時だけ使っていました。
SafeArrayの公式ヘルプを読みました。引数の意味と2次元まで作成できる点、理解しました。

恥をかいたついでに、無知を披露してしまいますが、
多次元の連想配列に代入する書き方を教えてください。
1時間程度彷徨いましたが、ヒントになる記事を見つけることができませんでした。
通常の多次元と同じ書き方でSyntaxErrorが出ます。
たぶん、とても簡単なことだと思うのですが・・・

DIM v[1][1]

v[0][0] = "value" // 通常の2次元はこの書き方で代入できる
PRINT v[0][0]

hashtbl h
h["hoge"] = split("foo bar baz") // splitでSafeArrayにする
print h["hoge"][0] // foo

h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
print h["hoge"][0]



Dictionaryも初耳でしたので、調べていました。
COMオブジェを経由して使える連想配列という認識を得ました(誤解してるかもですが)
こんなこともできるのか。と、改めてUWSCの魅力を感じていました。
そして、ここで回答をいただくたびに新しい言葉を教えてもらって感謝しています。

No.1177 2021/02/13(Sat) 16:42:51

Re: EVALで値の代入したい / stuncloud
> h["hoge"][0] = "f002" // 同じ書き方でもSyntaxErrorがでる
うわあ、確認不足でしたごめんなさい
これはおそらく連想配列の要素にインデックス指定して代入、をUWSCが許容していないということだと思います
値を読むだけならOKだけど代入は無理ということになりますね
つまりこの方法は使えない…ので忘れてください…ほんとすいません…

> COMオブジェを経由して使える連想配列という認識
そんな感じでOKです
例えば連想配列を関数の戻り値にしたいけど、仕様上できないので代わりにScripting.Dictionaryを使う
みたいな感じで使うことがあったりなかったりします

No.1179 2021/02/13(Sat) 18:57:59

以下のフォームに記事No.と投稿時のパスワードを入力すれば
投稿後に記事の編集や削除が行えます。
200/200件 [ ページ : << 1 ... 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >> ]

- HOME - お知らせ(3/8) - 記事検索 - 携帯用URL - フィード - ヘルプ - メール - 環境設定 -

- Skin: Modern v2.0 - Author: ロケットBBS -

Rocket Board Type-X (Free) Rocket BBS