C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: CopyFileWでコピー出来ない


(過去ログ 119 を表示中)

[トピック内 15 記事 (1 - 15 表示)]  << 0 >>

■69942 / inTopicNo.1)  CopyFileWでコピー出来ない
  
□投稿者/ 鯖の味噌 (1回)-(2014/02/13(Thu) 10:46:43)

分類:[VB.NET/VB2005 以降] 

2014/02/13(Thu) 10:52:44 編集(投稿者)
    Private Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileW" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Integer) As Integer

    Sub Main()

        Dim Result As Integer = CopyFile("\\?\C:\A.txt", "\\?\C:\B.txt", 0)

    End Sub

このコードを実行してもResult=0となりコピーできません。
どこを間違えているのでしょうか?

Windows7 64bit SP1
VS Express 2013 for Desktop
を使用しています。

引用返信 編集キー/
■69943 / inTopicNo.2)  Re[1]: CopyFileWでコピー出来ない
□投稿者/ shu (486回)-(2014/02/13(Thu) 10:57:00)
No69942 (鯖の味噌 さん) に返信
Cドライブのすぐ下に書こうとしてアクセス制限に引っかかっているのでは?
C:\の下にフォルダを作成してそこで試してみてはどうでしょう?
引用返信 編集キー/
■69945 / inTopicNo.3)  Re[2]: CopyFileWでコピー出来ない
□投稿者/ 鯖の味噌 (2回)-(2014/02/13(Thu) 11:06:38)
No69943 (shu さん) に返信
> ■No69942 (鯖の味噌 さん) に返信
> Cドライブのすぐ下に書こうとしてアクセス制限に引っかかっているのでは?
> C:\の下にフォルダを作成してそこで試してみてはどうでしょう?

早速のご返答有難うございます。
フォルダ「C:\CopyTemp」を作成して下のように試してみました。

Dim Result As Integer = CopyFile("\\?\C:\CopyTemp\A.txt", "\\?\C:\CopyTemp\B.txt", 0)

これでもコピーできませんでした。
「\\?\」を外して

CopyFile("C:\CopyTemp\A.txt", "C:\CopyTemp\B.txt", 0)

も試してみましたがコピーできませんでした。
CopyFileWの定義が間違っているのでしょうか?
引用返信 編集キー/
■69946 / inTopicNo.4)  Re[3]: CopyFileWでコピー出来ない
□投稿者/ shu (487回)-(2014/02/13(Thu) 11:13:56)
No69945 (鯖の味噌 さん) に返信

http://blog.livedoor.jp/akf0/archives/51271267.html
に丁度MarshalAs指定した定義が載っていたので
<MarshalAs(UnmanagedType.LPStr)> を各ファイル名引数の前に付加してみて下さい。
引用返信 編集キー/
■69947 / inTopicNo.5)  Re[1]: CopyFileWでコピー出来ない
□投稿者/ 魔界の仮面弁士 (529回)-(2014/02/13(Thu) 11:27:23)
No69942 (鯖の味噌 さん) に返信
> Private Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileW"
Private Declare Unicode Function 〜 と記述しないと、Unicode 版になりません。
Auto でも良いですが。
引用返信 編集キー/
■69948 / inTopicNo.6)  Re[4]: CopyFileWでコピー出来ない
□投稿者/ Hongliang (166回)-(2014/02/13(Thu) 11:28:47)
> <MarshalAs(UnmanagedType.LPStr)> を各ファイル名引数の前に付加してみて下さい。
CopyFileWなので、LPStrではなくLPWStrですね。

で思い出した、Unicode版の関数を使用するなら、Declare FunctionではなくDeclare Unicode Functionにする必要があります。
(そうするとStringは自動的にUnicodeで渡されるようになります)

あと、
If Result = 0 Then
Trace.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).ToString())
End If
などとして、エラーの内容をまず確認すべきです。
引用返信 編集キー/
■69949 / inTopicNo.7)  Re[2]: CopyFileWでコピー出来ない
□投稿者/ shu (488回)-(2014/02/13(Thu) 11:43:08)
No69947 (魔界の仮面弁士 さん) に返信
> ■No69942 (鯖の味噌 さん) に返信
>>Private Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileW"
> Private Declare Unicode Function 〜 と記述しないと、Unicode 版になりません。
> Auto でも良いですが。
そこでしたかmm


No69945 (鯖の味噌 さん) に返信
ところでAPIで記述されていますがSystem.IO.File.Copy等でファイルコピーするのでは
用が足りないのでしょうか?長すぎるファイル名を対象としているということなのでしょうか?
引用返信 編集キー/
■69950 / inTopicNo.8)  Re[3]: CopyFileWでコピー出来ない
□投稿者/ 鯖の味噌 (3回)-(2014/02/13(Thu) 11:46:59)
No69949 (shu さん) に返信
> ■No69947 (魔界の仮面弁士 さん) に返信
>>■No69942 (鯖の味噌 さん) に返信
> >>Private Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileW"
>>Private Declare Unicode Function 〜 と記述しないと、Unicode 版になりません。
>>Auto でも良いですが。
> そこでしたかmm
>
>
> ■No69945 (鯖の味噌 さん) に返信
> ところでAPIで記述されていますがSystem.IO.File.Copy等でファイルコピーするのでは
> 用が足りないのでしょうか?長すぎるファイル名を対象としているということなのでしょうか?


はい。長すぎるファイル名を対象にしています。
引用返信 編集キー/
■69951 / inTopicNo.9)  Re[5]: CopyFileWでコピー出来ない
□投稿者/ 鯖の味噌 (4回)-(2014/02/13(Thu) 11:47:58)
No69948 (Hongliang さん) に返信
>><MarshalAs(UnmanagedType.LPStr)> を各ファイル名引数の前に付加してみて下さい。
> CopyFileWなので、LPStrではなくLPWStrですね。
>
> で思い出した、Unicode版の関数を使用するなら、Declare FunctionではなくDeclare Unicode Functionにする必要があります。
> (そうするとStringは自動的にUnicodeで渡されるようになります)
>
> あと、
> If Result = 0 Then
> Trace.WriteLine(new Win32Exception(Marshal.GetLastWin32Error()).ToString())
> End If
> などとして、エラーの内容をまず確認すべきです。

ありがとうございます。
ご指摘のとおり、エラーの内容を確認します
引用返信 編集キー/
■69952 / inTopicNo.10)  Re[1]: CopyFileWでコピー出来ない
□投稿者/ 鯖の味噌 (5回)-(2014/02/13(Thu) 11:51:04)
No69942 (鯖の味噌 さん) に返信
> 2014/02/13(Thu) 10:52:44 編集(投稿者)
>
> Private Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileW" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Integer) As Integer
>
> Sub Main()
>
> Dim Result As Integer = CopyFile("\\?\C:\A.txt", "\\?\C:\B.txt", 0)
>
> End Sub
>
> このコードを実行してもResult=0となりコピーできません。
> どこを間違えているのでしょうか?
>
> Windows7 64bit SP1
> VS Express 2013 for Desktop
> を使用しています。

返答をくださいました皆様ありがとうございました。
以下のように記述し、コピー出来ました。

Private Declare Unicode Function CopyFile Lib "kernel32.dll" Alias "CopyFileW" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Integer) As Integer
Sub Main()
Dim Result As Integer = CopyFile("\\?\C:\CopyTemp\A.txt", "\\?\C:\CopyTemp\B.txt", 1)
If Result = 0 Then
Trace.WriteLine(New ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).ToString())
End If
End Sub


MarshalAsは付けていませんが問題ないでしょうか?
引用返信 編集キー/
■69954 / inTopicNo.11)  Re[2]: CopyFileWでコピー出来ない
□投稿者/ shu (489回)-(2014/02/13(Thu) 12:00:53)
No69952 (鯖の味噌 さん) に返信
>
> MarshalAsは付けていませんが問題ないでしょうか?
No69948 Hongliangさんが回答されているように
Unicodeで渡されるということなので問題ないと思います。


引用返信 編集キー/
■69955 / inTopicNo.12)  Re[3]: CopyFileWでコピー出来ない
□投稿者/ 鯖の味噌 (6回)-(2014/02/13(Thu) 12:06:31)
No69954 (shu さん) に返信
> ■No69952 (鯖の味噌 さん) に返信
>>
>>MarshalAsは付けていませんが問題ないでしょうか?
> No69948 Hongliangさんが回答されているように
> Unicodeで渡されるということなので問題ないと思います。
>
>

ご返答有難うございます!
解決済み
引用返信 編集キー/
■69956 / inTopicNo.13)  Re[2]: CopyFileWでコピー出来ない
□投稿者/ 魔界の仮面弁士 (530回)-(2014/02/13(Thu) 12:07:24)
No69952 (鯖の味噌 さん) に返信
> MarshalAsは付けていませんが問題ないでしょうか?

あった方が良いですが、無くても大抵は大丈夫です。

現状のコードだと、たとえば
 Dim s1 As String = "\\?\C:\A.xls"
 Dim s2 As String = "\\?\C:\B.xls"
 Dim a As String = s1
 Dim b As String = s2
 Dim Result As Integer = CopyFile(s1, s2, 1)
を実行した後、「If s1 Is a Then」や「If s2 Is b Then」が False になってしまいます。
本来の型は LPTSTR ではなく LPCTSTR のはずなのですけれどね。


なので、厳密には
 ( _
  <MarshalAs(UnmanagedType.LPStr)> ByVal lpExistingFileName As String, _
  <MarshalAs(UnmanagedType.LPStr)> ByVal lpNewFileName As String, _
  <MarshalAs(UnmanagedType.Bool)> ByVal bFailIfExists As Boolean) _
 As <MarshalAs(UnmanagedType.Bool)> Boolean
と定義するのが正しいことになります。
これならば、「If s1 Is a Then」は True のままとなります。


あるいは、Declare ではなく <DllImport> を使うこともできます。
DllImportAttribute であれば、MarshalAsAttribute を指定せずとも
「If s1 Is a Then」が True のままとなります。
引用返信 編集キー/
■69963 / inTopicNo.14)  Re[1]: CopyFileWでコピー出来ない
□投稿者/ 鯖の味噌 (7回)-(2014/02/13(Thu) 18:27:52)
No69942 (鯖の味噌 さん) に返信
> 2014/02/13(Thu) 10:52:44 編集(投稿者)
>
> Private Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileW" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal bFailIfExists As Integer) As Integer
>
> Sub Main()
>
> Dim Result As Integer = CopyFile("\\?\C:\A.txt", "\\?\C:\B.txt", 0)
>
> End Sub
>
> このコードを実行してもResult=0となりコピーできません。
> どこを間違えているのでしょうか?
>
> Windows7 64bit SP1
> VS Express 2013 for Desktop
> を使用しています。

ご教授ありがとうございました。
最終的に以下のように記述し、コピーすることが出来ました。

Private Declare Unicode Function CopyFile Lib "kernel32.dll" Alias "CopyFileW" (<MarshalAs(UnmanagedType.LPStr)> ByVal lpExistingFileName As String, _
<MarshalAs(UnmanagedType.LPStr)> ByVal lpNewFileName As String, _
<MarshalAs(UnmanagedType.Bool)> ByVal bFailIfExists As Boolean) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
Sub Main()
Dim Result As Integer = CopyFile("\\?\C:\CopyTemp\A.txt", "\\?\C:\CopyTemp\B.txt", 1)
If Result = 0 Then
Trace.WriteLine(New ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).ToString())
End If
End Sub

解決済み
引用返信 編集キー/
■69964 / inTopicNo.15)  Re[2]: CopyFileWでコピー出来ない
□投稿者/ 魔界の仮面弁士 (531回)-(2014/02/13(Thu) 18:45:03)
No69963 (鯖の味噌 さん) に返信
> 最終的に以下のように記述し、コピーすることが出来ました。
Declare を Boolean 型で宣言しているのに、
呼び出し側で Integer 型を使っているのは何故ですか?

> Trace.WriteLine(New ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).ToString())
ちなみに Marshal.GetLastWin32Error() メソッドの代わりに、
Err.LastDllError プロパティを使っても同じ結果が得られます。蛇足までに。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -