#python #file #winapi #server
#python #файл #winapi #сервер
Вопрос:
В настоящее время я исправляю код для клиента, который может загружать файлы из облака. Клиент временно загружает файл, и когда файл закрывается (завершается), он отправляется обратно в облако. Вот полный код:
import socket
import os
from OpenFile import *
from Registry_Change import *
import win32con
import win32api
import win32event
from win32com.shell import shellcon
from win32com.shell.shell import ShellExecuteEx
class Application(object):
def __init__(self):
"""
:param request: the request of the file to receive from server
"""
# initiates request (clicked file path)
self.request = sys.argv[SECOND]
reg = Read_Registry()
ip, port = reg.get_ip_port()
self.ip = ip
self.port = port
# initiates socket
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.ip, self.port))
# sends the request to the server
Application.send_request_to_server(self.sock, "DOWNLOAD_FILE " self.request)
format = Application.read_server_response(self.sock).decode()
self.path_file = self.download(format)
self.start_file_and_wait()
self.sock.close()
except Exception as msg:
print(win32api.GetLastError())
print("connection error:", msg)
@staticmethod
def valid_file(path):
"""
checks if the path is a file that exists
"""
if os.path.isfile(path):
return True
return False
@staticmethod
def delete_file(file_path):
"""
deletes file
"""
os.remove(file_path)
@staticmethod
def read_server_response(server_socket_choice):
"""
reads the length and according to that, it reads the rest
of the message
"""
try:
length_of_message = server_socket_choice.recv(BYTE).decode()
if length_of_message.isdigit():
return server_socket_choice.recv(int(length_of_message))
except Exception as msg:
print("at read_server_response:", msg)
return SERVER_FELL
@staticmethod
def send_request_to_server(server_socket, request):
"""
Send the request to the server.
First the length of the request (2 digits), then the request itself
Example: '04EXIT'
Example: '12DIR c:cyber'
"""
server_socket.
send((str(len(request)).zfill(MSG_FILL) request).encode())
def download(self, format):
"""
saves the given chunks to a file in the client
"""
try:
file = Application.new_format_path(self.request, format)
new_location = Application.make_new_file_path(TEMPORARY_FILES, file)
# check if the file is valid
check_len = self.sock.recv(BYTE).decode()
check = self.sock.recv(int(check_len))
if check != FILE_DOESNT_EXIST:
client_file = open(new_location, 'wb')
# write what we took out
client_file.write(check)
done = False
while not done:
byte_message_len = self.sock.recv(BYTE)
length = byte_message_len.decode()
if length.isdigit():
real_len = int(length)
data = self.sock.recv(real_len)
if data == FILE_END:
done = True
else:
client_file.write(data)
client_file.close()
return new_location
else:
return 'nothing'
except Exception as msg:
print("at download:", msg)
def upload(self, file_path):
"""
Sends a file from the server to the client
"""
if Application.valid_file(file_path):
client_file = open(file_path, 'rb')
content = client_file.read(BYTE_NUMBER)
while content != b'':
Application.send_binary_response_to_server(content, self.sock)
content = client_file.read(BYTE_NUMBER)
client_file.close()
Application.send_binary_response_to_server(FILE_END, self.sock)
Application.delete_file(file_path)
Application.make_imaginary_file(file_path)
return Application.read_server_response(self.my_socket)
else:
Application.send_response_to_server(FILE_DOESNT_EXIST, self.sock)
return FILE_DOESNT_EXIST
@staticmethod
def make_new_file_path(new_path, folder):
"""
:param new_path: new path of file to merge
:return: the new path
"""
comp = folder.split("\")
return new_path "\" comp[END]
@staticmethod
def new_format_path(path, format):
"""
:param format: the new format
:return: the same path but with new format
"""
path_format = path.split('.')
path_format[SECOND] = format
return ".".join(path_format)
def start_file_and_wait(self):
"""
:param fname: the file path - temporary
:return: opens and continues when closed
"""
rc = ShellExecuteEx(
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
nShow=win32con.SW_SHOW,
lpFile=self.path_file)
hproc = rc['hProcess']
win32event.WaitForSingleObject(hproc, win32event.INFINITE)
win32api.CloseHandle(hproc)
app = Application()
Теперь, событие win32.WaitForSingleObject(hproc, win32event.БЕСКОНЕЧНАЯ) команда не работает и возвращает ошибку: «(6, ‘WaitForSingleObject’, ‘Дескриптор недействителен.’)».
Когда я попытался использовать функцию start_file_and_wait(self) в отдельном файле, это сработало:
def start_file_wait(fname):
import win32con
import win32api
import win32event
from win32com.shell import shellcon
from win32com.shell.shell import ShellExecuteEx
rc = ShellExecuteEx(
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
nShow=win32con.SW_SHOW,
lpFile=fname)
hproc = rc['hProcess']
win32event.WaitForSingleObject(hproc, win32event.INFINITE)
win32api.CloseHandle(hproc)
def main():
start_file_wait("E:\12\alice-chapter-1.txt")
print("hi")
if __name__ == '__main__':
main()
Я не знаю, как это исправить. кто-нибудь может мне помочь?
Спасибо!
Комментарии:
1. Он не работает с файлами, которые не являются текстовыми файлами!!!
2. Я не программирую на Python, но я собираюсь предположить, что вы создаете поток / процесс, а затем ожидаете, что этот поток / процесс вернется с WaitForSingleObject?
Ответ №1:
Он не работает с файлами, которые не являются текстовыми файлами
Как вы сказали, вы не указали подходящий глагол для ShellExecuteEx
, в соответствии с параметром:
lpVerb :
… Этот параметр может быть нулевым, и в этом случае используется глагол по умолчанию, если он доступен. Если нет, используется глагол «открыть». Если ни один из глаголов недоступен, система использует первый глагол, указанный в реестре.
Может произойти сбой и вернуть недопустимый hProcess
дескриптор, если он не может найти соответствующее приложение для открытия файла. Вы должны указать допустимый глагол в соответствии с файлом, который вы открываете. Или укажите исполняемый файл приложения, соответствующий файлу как lpFile
, и укажите файл как lpParameters
.
Вы можете обратиться к следующему документу: Запуск приложений