• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:SHFileOperationについて)

SHFileOperationについて

このQ&Aのポイント
  • APIのファイルフォルダコピー関数、SHFileOperation()がエラーを発生させる原因または、回避・解消する方法を教えてください
  • VisualBasicで操作している際に、SHFileOperation()を実行するとデザイン環境または実行したexeが強制終了し、エラーメッセージが表示される問題が発生しています
  • Windows2000Pro環境では問題が起こりますが、WindowsXP環境では正常にファイルコピーが完了します

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

構造体の定義自体はあっていました。 ただ、この構造体自体が曲者で、 >fFlags As Integer '操作フラッグ(FOF_xxx) とIntegerが1つだけいます。 普通はWinAPIで使用する構造体は、4バイト(32bit)毎に構造体のメンバが整列されているのですが、このIntegerのせいで、このメンバ以降のメモリ上の位置がずれてしまっています。 VB6では自動的に4バイトの位置にメンバの位置を合わせてしまうため、VBで定義した構造体と、APIが要求する構造体の定義に違いが出てきてしまい、エラーが発生してしまいます。 >ちなみに、4つ目の操作フラグの"FOF_SIMPLEPROGRESS"を削除してみたら不具合が起きませんでした。 構造体の一番最後のメンバであるlpszProgressTitleは、 FOF_SIMPLEPROGRESSを指定したときのみ参照されます。 つまり、FOF_SIMPLEPROGRESSが指定されたときに、 lpszProgressTitleをAPI内部で参照しに行ったが、 構造体のアライメントの関係でlpszProgressTitleの位置がずれてしまっていたため、ただしく"コピー"という文字列が取得できず、エラーとなってしまった。 ということです。 どうしてもタイトル文字列を変えたいということですと、 メンバのずれを意識して自分でアドレスの値を指定していくしかなさそうですね。

natural_aspirate
質問者

お礼

takat_tetsuさん、ご回答ありがとうございます。 原因を理解できました。結果としてはVB6でのプログレスバー付き(及びタイトル付き)の使用を避けようと思います。今後もAPI使用時は引数の4バイトは意識しておいた方が良さそうですね。プログレスバーはまた別オブジェクトでも作成してみます。 お忙しいところ、ありがとうございました。感謝します。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

構造体の定義が怪しいかも。 どんな定義書いてます?

natural_aspirate
質問者

お礼

taka_tetsuさん、ご指摘恐れ入ります。 補足にて記述いたします。

natural_aspirate
質問者

補足

以下、定義したい構造体です。 Type SHFILEOPSTRUCT hWnd As Long 'ウインドウのハンドル wFunc As Long '操作方法 pFrom As String   '操作元のファイル名・ディレクトリ名 pTo As String '操作先のファイル名・ディレクトリ名 fFlags As Integer '操作フラッグ(FOF_xxx) fAnyOperationsAborted As Long hNameMappings As Long lpszProgressTitle As String End Type ちなみに、4つ目の操作フラグの"FOF_SIMPLEPROGRESS"を削除してみたら不具合が起きませんでした。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ファイルやフォルダをごみ箱に移動 その2

    直下の質問「ファイルやフォルダをごみ箱に移動」をさせていただいた者です。 「ファイルやフォルダをごみ箱に移動」を行うActiveX DLLを作成して、無事動作させることができました。が、新しい問題が発生してしまいました。 作成したルーチンは、以下の通りです。 ----- Public Sub GoToTrash(inStrItemNames As String, Optional inBlnConfirm As Boolean) Dim ShellOp As SHFILEOPSTRUCT Dim flg As Integer ' 確認メッセージの表示? If IsMissing(inBlnConfirm) Then inBlnConfirm = False If inBlnConfirm Then flg = FOF_ALLOWUNDO Else flg = FOF_ALLOWUNDO Or FOF_NOCONFIRMATION End If With ShellOp .hwnd = 0 .wFunc = FO_DELETE .pFrom = inStrItemNames .fFlags = flg End With ' ごみ箱へ削除実行 SHFileOperation(ShellOp) End Sub ----- これをActiveX化して、ASPから呼び出すと、ちゃんと動作して、指定されたファイルはごみ箱に直行します。しかし、存在しないファイルなどが指定されると、たとえ、FOF_NOCONFIRMATIONを指定したとしても、確認のDialogBoxが表示されてしまうようです。(WSHで確認しました) こうなると、ASPではスクリプトエンジンが処理を中断してしまうようで、以降再起動しない限り、ASPページが全く表示されなくなってしまいます。 なにか良い手段は無いでしょうか?

  • ファイルやフォルダのごみ箱への移動 2

    ファイル(もしくはフォルダ)を一つ選択してごみ箱に捨てるとき、「いいえ」を押したら別の処理をさせようとしているのですが、作ってみた関数だと上手くいきません。 どういうわけか常に 0 が返ってきます。 --------------------------------- Public Function FileToDust(FName As String) As Long 'ファイルをごみ箱へ送る 'FName --- ファイル、フォルダ名を入れる文字列変数   Dim FOS As SHFILEOPSTRUCT   With FOS     .hWnd = 0     .wFunc = FO_DELETE     .pFrom = FName     .fFlags = FOF_ALLOWUNDO   End With   FileToDust = SHFileOperation(FOS) End Function --------------------------------------- どこが悪いんでしょうか。本来なら、処理が中断されれば 0 以外が返ってくるらしいのですが…… 0 が返ってきたとき成功したと思って前回の質問をすぐに打ち切ってしまったので、もう一度質問させていただきます。 前回の質問 http://oshiete1.goo.ne.jp/kotaeru.php3?q=466239 よろしくお願いします。 ---------------- 開発環境 VB6.0SP5 WinME

  • エラーメッセージはコピペできないのでしょうか?

    MsgBoxはctrl+cでコピペできるのですが エラーメッセージはコピペできないのでしょうか? Sub Sample() Dim i As Long i = "a" End Sub でエラーを発生させて、コピーしてみても何も起こりません。

  • Active Basic 他のアプリケーションを終了させる

    Active Basic4.23.00を使用しています。 指定したほかのプロセスを終了させようと思っているのですが、 なかなか上手くいきません。 Dim hWnd As HWND Dim err As Long Dim code As DWord hWnd=FindWindow("notepad",NULL) If hWnd=NULL Then MessageBox(hMainWnd,"FindWindowでエラーが発生!","Error",MB_OK or MB_ICONHAND) Exit Sub End If GetExitCodeProcess(hWnd,code) If code=STILL_ACTIVE Then MessageBox(hMainWnd,"GetExitCodeProcessでSTILL_ACTIVEが返った!","Error",MB_OK or MB_ICONHAND) Exit Sub End If err=TerminateProcess(hWnd,code) If err=0 Then MessageBox(hMainWnd,"TerminateProcessでエラーが発生!","Error",MB_OK or MB_ICONHAND) MessageBox(0,Str$(code),"GetExitCodeProcessで取得したコード",MB_OK or MB_ICONINFORMATION) Exit Sub End If このようなコードを書きました。 すみませんが、間違いの指摘のほうをお願いします。 それと、『FindWindow』関数についてです。 ヘルプに、 >lpClassName >検索するクラス名を指定します。必要のないときは、NULL を指定することができます。 とありますが、クラス名≒プロセス名と考えてもいいのでしょうか。 また、lpClassNameを指定し、lpWindowNameにNULLを指定(今回のコードのような場合)では、ハンドルを取得できないのでしょうか。 すみませんが、ご教授をお願いします。

  • VBを使ってのCD-RWへのバックアップ方法を教えてください。

    こんにちは。よろしくお願いします。 VB5を使って開発しています。 パソコンの環境はWindowsXP(SP2)、データはAccess2003のMDBデータとスキャナで取り込んだ画像ファイルです。 上記2データをCD-RWにバックアップする処理をフォーム上のコマンドボタンを押して実行したいと考えています。 いろいろなサイトなどを探してみてFilecopyやSHFileOperationといったコピーの方法があると知りどちらも試してみたのですが、うまくいきません。間違っている箇所すらわからない状態です。CD-RWにバックアップを取ることは不可能なのでしょうか。また正しい方法が別に存在するのでしょうか。ご指摘、アドバイスをお願いいたします。 下は実際に作った処理です。 ----------------------------------------------------- Filecopy "D:\data\*.*","E:\back\*.*" ------------------------------------------------------ Private Declare Function SHFileOperation Lib "shell32" Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long Private Type SHFILEOPSTRUCT hwnd As Long wFunc As Long pFrom As String pTo As String fFlags As Integer fAnyOperationsAborted As Long hNameMappings As Long lpszProgressTitle As String End Type Private Const FO_COPY = &H2 Private Const FO_DELETE = &H3 Private Const FO_MOVE = &H1 Private Const FO_RENAME = &H4 Private Sub Command1_Click() Dim Ret As Long Dim sf As SHFILEOPSTRUCT sf.hwnd = Me.hwnd sf.wFunc = FO_COPY sf.pFrom = "D:\data\*" sf.pTo = "E:\back\" Ret = SHFileOperation(sf) If Ret <> 0 Then MsgBox "失敗しました。" End Sub

  • フォルダの削除について

    Cでのフォルダの削除方法が分からず困っています。 ファイルの削除は"remove()"で行うことができましたが、フォルダは同じ方法ではできないようです。 No.394869 の質問を参考にして"SHFileOperation()"を使用してみたのですが、エラー担ってしまいました。(Access Violation) "SHFILEOPSTRUCT"の値の設定(ハンドルなど)がうまくいっていないのかな?とも思ったのですが、 どうすればよいのかわかりません。 別の方法があればそれでもいいですし、"SHFileOperation()"の使い方(ハンドルの設定など)を知りたいのでよろしくお願いします。 ちなみに、今は以下の方法でやっていました。 フォルダ内(testfolder)は空の状態です。 ******************************************** SHFILEOPSTRUCT shfileop; /* ファイルの削除 */ shfileop.hwnd = NULL; shfileop.wFunc = FO_DELETE; shfileop.pFrom = "C:\\TEST\\testfolder"; shfileop.fFlags = FOF_SIMPLEPROGRESS|FOF_NOCONFIRMATION; SHFileOperation(&shfileop);

  • エラーメッセージをコピーするには?

    例えば Sub test() Dim i As Integer i = "a" End Sub というコードは 実行時エラー13が発生します。 このエラーメッセージの内容をコピーする事は可能でしょうか? エラー処理をし err.Descriptionで取得するしかないですか?

  • イベントプロパティに指定した式 クリック時 でエラ

    以前http://okwave.jp/qa/q7848134.html で質問したものです。 2名の方ご回答ありがとうございました。 頂いたご回答を実行するとエラーになるので教えてください。 新規にフォームを作り、タブとコマンドボタンを置き、 Sub delPage() Dim myForm As String Dim frm As Form Dim i As Long myForm = "フォーム1" DoCmd.OpenForm myForm, acDesign Set frm = Forms(myForm) For i = frm!タブ0.Pages.Count - 1 To 2 Step -1 frm!タブ0.Pages.Remove (i) Next DoCmd.Close acForm, myForm, acSaveYes Set frm = Nothing End Sub を実行すると、ページが消えフォームが閉じられますが、再度フォームを開いた時に、 「イベントプロパティに指定した式 クリック時 でエラーが発生しました: Microsoft Office AccessがOLEサーバーまたはActiveXコントロールと通信指定いるときにエラーが発生しました。」が出てしまいます。 コードを消したり、タブを削除してもこのコードはずっと出るようになってしまいました。 (フォームにコマンドボタンしかなくても) なぜこのコードを実行すると、このようなエラーがでるのでしょうか? http://www.accessclub.jp/bbs2/0033/beginter10779.html をみると、 「OCX/ActiveX コントロールを貼り付けたが、不要になって外すなどして、無意味な参照設定が残ることがあります。」 となっていますが、コマンドボタンとタブとページだけで、ActiveX コントロールは貼りつけてないし、 参照設定は何もいじってません。 新規にmdbファイルを作り、同じ事をすると同じエラーメッセ―ジが出ます。 当方win7、オフィス2007です。 ご回答よろしくお願いします。

  • VBAの書き方を教えてください。パート2

    10月12日に、こちらでVBAの書き方をお聞きした内容の続きになります。 http://okwave.jp/qa/q7744550.html FrmLevelInitの実行が定期的に停止し、ログインできなくなる。 または、一度ID、Passを入力してはじかれた後、Passを再入力し直すとログイン出来る。 の2点が発生してしまいます。 環境がRuntimeを使って使用しているので、作成者が何度もVBAを立ち上げて実行し、再配布している状態です。 すみませんがお手伝い頂けますでしょうか。 Public Sub FrmLevelInit(ParamArray v()) On Error Resume Next If (IsMissing(v)) Then sIdSave = "" sNameSave = "" iUserLevel = 0 Else sIdSave = v(0) sNameSave = v(1) iUserLevel = CLng(v(2)) End If End Sub ' 指定されたフォームのコントロールのタグをチェック Public Sub FrmLevelSet(frm As Form) Dim ctl As Control Dim i As Long For Each ctl In frm.Controls With ctl i = InStr(.Tag, "," & iUserLevel & ",") If (i > 0) Then .Enabled = False End With Next End Sub Public Function LoginId() As String ' ID を返す LoginId = sIdSave End Function Public Function LoginName() As String ' 名前を返す LoginName = sNameSave End Function

  • 標準モジュールからフォームをコントロールしたい

    こんにちは。 標準モジュールからフォームのリストボックスに文字を追加したいんですが、うまくいきません。 まず、button1をクリックすると、共通モジュールのサブルーチンを呼び出します。そして引数"0"を渡すと、Form1のListBox1に"hello"を追加したいのです。 実行させると、エラーはでないのですが、追加されるはずの"hello"がListBox1に追加されません。 たぶん     frm1.ListBox1.Items.Add("hello") あるいは    Dim frm1 As New Form1() あたりの宣言の仕方がまずいのだと思うんですが... どなたか、ご教授よろしくお願いします。 ■共通モジュール Module Module1 Dim frm1 As New Form1() Sub PC(ByVal PCrecieve As String) If PCrecieve = "0" Then frm1.ListBox1.Items.Add("hello") End If End Sub End Module ■フォーム Public Class Form1 Inherits System.Windows.Forms.Form Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Call PC("0") End Sub End Class