Issue
I am following this tutorials here where the CopyFile function calling the windows API just dosen’t work for me. This is the code I am using (just changed the username)
from ctypes import *
CopyFile = windll.kernel32.CopyFileA
CopyFile("C:\Windows\System32\calc.exe", "C:\\Users\legion\Desktop\calc.exe", False)
I tried changing the parameters, file path, I tried same file to the same directory changing False to True so that I may get an error or prompt that the file already exists. It just dosen’t work. If you haven’t worked with Ctypes (like me) and don’t know the answer, please try and try this snippet on your machine.
Solution
The 1st thing that I see, is that some backslashes (\) in the paths are not escaped. It won’t be a problem in this particular case, but it’s better to always escape them.
I modified your code a bit.
code00.py
#!/usr/bin/env python
import ctypes as ct
import os
import sys
def main(*argv):
src = r"C:\Windows\System32\calc.exe"
dst = os.path.join(os.getcwd(), "calc.exe")
kernel32 = ct.windll.kernel32
copy_file_a = kernel32.CopyFileA
copy_file_w = kernel32.CopyFileW
reta = copy_file_a(src, dst, False)
retw = copy_file_w(src, dst, False)
print("{:s} returned: {:d}\n{:s} returned: {:d}\n".format(copy_file_a.__name__, reta, copy_file_w.__name__, retw))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[[email protected]:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_02.07.18_test0\Scripts\python.exe" code00.py Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] 064bit on win32 CopyFileA returned: 1 CopyFileW returned: 0 Done. [[email protected]:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" code00.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 CopyFileA returned: 0 CopyFileW returned: 1 Done.
Notes:
-
According to [MS.Docs]: CopyFile function:
If the function succeeds, the return value is nonzero.
-
I’ve added CopyFileW in the mix
-
According to output, CopyFileA fails with Python 3 (I’ve figured out that this is your scenario), and CopyFileW fails with Python 2.
That happens because in Python 2, strings are 008bit (char * based), while in Python 3 they are Unicode (016bit (wchar_t * based) on Win).
Check [SO]: Passing utf-16 string to a Windows function (@CristiFati’s answer) for more details -
Since the ANSI (A) version of a function has some limitations compared to its Wide (W) version, it’s recommended to use the latter one
We have a cause for the failure, but we’re not quite there yet. Here’s a more elaborate example.
code01.py:
#!/usr/bin/env python
import ctypes as ct
import os
import sys
def main(*argv):
src = r"C:\Windows\System32\calc.exe"
dst = os.path.join(os.getcwd(), "calc.exe")
kernel32 = ct.windll.kernel32
copy_file_a = kernel32.CopyFileA
copy_file_a.argtypes = (ct.c_char_p, ct.c_char_p, ct.c_int)
copy_file_a.restype = ct.c_int
copy_file_w = kernel32.CopyFileW
copy_file_w.argtypes = (ct.c_wchar_p, ct.c_wchar_p, ct.c_int)
copy_file_w.restype = ct.c_int
reta = copy_file_a(src.encode(), dst.encode(), False)
retw = copy_file_w(src, dst, False)
print("{:s} returned: {:d}\n{:s} returned: {:d}\n".format(copy_file_a.__name__, reta, copy_file_w.__name__, retw))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Notes:
-
Added some string encoding
-
Set argtypes and restype for functions "imported" by CTypes ([SO]: C function called from Python via ctypes returns incorrect value (@CristiFati’s answer))
Output:
[[email protected]:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_02.07.18_test0\Scripts\python.exe" code01.py Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] 064bit on win32 CopyFileA returned: 1 CopyFileW returned: 1 Done. [[email protected]:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" code01.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 CopyFileA returned: 1 CopyFileW returned: 1 Done.
Answered By – CristiFati
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0