Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt SHFileOperation使目录“为”;“不可剥夺”;_Qt_Winapi_Win32 Process_Shfileoperation - Fatal编程技术网

Qt SHFileOperation使目录“为”;“不可剥夺”;

Qt SHFileOperation使目录“为”;“不可剥夺”;,qt,winapi,win32-process,shfileoperation,Qt,Winapi,Win32 Process,Shfileoperation,好的,我有一个应用程序,它在%TEMP%目录中创建一个子目录,以在应用程序仍在运行时保留一些中间文件。当应用程序即将退出时,我将调用一个清理函数,以便再次从%TEMP%递归删除我的子目录,这样我们就不会留下任何“垃圾”文件。到目前为止,这在99.9%的情况下效果良好。但在一些非常罕见的情况下,清理功能无法删除我的子目录!测试表明,当清理成功时,它总是在第一次尝试时这样做。而且,当它失败时,在第一次尝试中,重试没有帮助。我可以重试9999次,但它会再次失败9999次。真倒霉 所以,很明显,“我的”

好的,我有一个应用程序,它在%TEMP%目录中创建一个子目录,以在应用程序仍在运行时保留一些中间文件。当应用程序即将退出时,我将调用一个清理函数,以便再次从%TEMP%递归删除我的子目录,这样我们就不会留下任何“垃圾”文件。到目前为止,这在99.9%的情况下效果良好。但在一些非常罕见的情况下,清理功能无法删除我的子目录!测试表明,当清理成功时,它总是在第一次尝试时这样做。而且,当它失败时,在第一次尝试中,重试没有帮助。我可以重试9999次,但它会再次失败9999次。真倒霉

所以,很明显,“我的”目录由于某种原因被阻止了。现在,如果“我的”目录中还有一些文件(或子目录),我就会理解这一点。但它是完全空的No文件(甚至不是隐藏的!)和No子目录。只是一个空目录。但它仍然无法删除。为了让事情变得更加模糊,我只是没能从自己的流程中删除它。它可以从Windows资源管理器或Total Commander中删除,即使我的进程仍在运行

现在,经过几个小时的测试,我发现应该归咎于SHFileOperation()。在某些情况下,我使用SHFileOperation()将文件复制到“我的”目录。而且,每当我这样做,这使得该目录“不可删除”,原因不明!再次澄清:我通过SHFileOperation()复制到“我的”目录的文件可以完全删除。它是可以不再删除的目录-仅从“我的”流程中删除。使用CopyFile()而不是SHFileOperation()立即解决了问题。我仍然想了解SHFileOperation()函数的运行情况

如果有人有主意,我很高兴知道

问候


~更新#1~

好的,根据要求,我总结了一个例子:

#define COPY_METHOD 0

static wchar_t *pathToBuffer(const QString &path)
{
    const QString nativePath = QDir::toNativeSeparators(path);
    wchar_t *buffer = new wchar_t[nativePath.length() + 2];
    wcscpy_s(buffer, path.length() + 2, (const wchar_t*) nativePath.utf16());
    buffer[nativePath.length()] = buffer[nativePath.length() + 1] = L'\0';
    return buffer;
}

bool some_function(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag)
{
    emit messageLogged(QString("Copy file \"%1\" to \"%2\"").arg(sourceFile, outputFile));

/*---------------------------*/
#if(COPY_METHOD == 0)
/*---------------------------*/

    QScopedArrayPointer<wchar_t> srcBuffer(pathToBuffer(sourceFile));
    QScopedArrayPointer<wchar_t> outBuffer(pathToBuffer(outputFile));

    SHFILEOPSTRUCTW fileOperation;
    memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));

    fileOperation.wFunc  = FO_COPY;
    fileOperation.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_FILESONLY;
    fileOperation.pFrom  = srcBuffer.data();
    fileOperation.pTo    = outBuffer.data();

    emit statusUpdated(0);
    int result = SHFileOperationW(&fileOperation);
    emit statusUpdated(100);

    return (result == 0 && fileOperation.fAnyOperationsAborted == false);

/*---------------------------*/
#elif(COPY_METHOD == 1)
/*---------------------------*/

    emit statusUpdated(0);
    const BOOL success = CopyFile((const wchar_t*) QDir::toNativeSeparators(sourceFile).utf16(), (const wchar_t*) QDir::toNativeSeparators(outputFile).utf16(), FALSE);
    emit statusUpdated(100);

    return (success != FALSE);

/*---------------------------*/
#elif(COPY_METHOD == 2)
/*---------------------------*/

    if(QFile::exists(outputFile))
    {
        QFile::remove(outputFile);
    }

    emit statusUpdated(0);
    QFile src(sourceFile);
    const bool success = src.copy(outputFile);
    emit statusUpdated(100);

    if(!success)
    {
        emit messageLogged(QString("Failed to copy file: %1").arg(src.errorString()));
    }

    return success;

/*---------------------------*/
#else
/*---------------------------*/

#error Invalid copy method specified!

/*---------------------------*/
#endif //COPY_METHOD
/*---------------------------*/
}
#定义复制方法0
静态wchar_t*路径缓冲(常量QString&path)
{
常量QString nativePath=QDir::音调分隔符(path);
wchar_t*buffer=新的wchar_t[nativePath.length()+2];
wcscpy_s(buffer,path.length()+2,(const wchar_t*)nativePath.utf16());
缓冲区[nativePath.length()]=缓冲区[nativePath.length()+1]=L'\0';
返回缓冲区;
}
bool some_函数(const QString和sourceFile、const QString和outputFile、volatile bool*abortFlag)
{
emit messageLogged(QString(“将文件\%1\”复制到\%2\).arg(sourceFile,outputFile));
/*---------------------------*/
#如果(复制方法==0)
/*---------------------------*/
QScopedarray指针srcBuffer(路径缓冲(源文件));
QScopedarray指针溢出器(pathToBuffer(outputFile));
SHFILEOPSTRUCTW文件操作;
memset(&fileOperation,0,sizeof(SHFILEOPSTRUCTW));
fileOperation.wFunc=FO_COPY;
fileOperation.fFlags=FOF|u SILENT | FOF|u noconfirmkdir | FOF|u noerrorrui | FOF|u FILESONLY;
fileOperation.pFrom=srcBuffer.data();
fileOperation.pTo=exputffer.data();
发射状态更新(0);
int result=SHFileOperationW(&fileOperation);
发射状态更新(100);
返回(结果==0&&fileOperation.FanyOperationsPorted==false);
/*---------------------------*/
#elif(复制方法==1)
/*---------------------------*/
发射状态更新(0);
const BOOL success=CopyFile((const wchar_t*)QDir::tonativeparators(sourceFile).utf16(),(const wchar_t*)QDir::tonativeparators(outputFile).utf16(),FALSE);
发射状态更新(100);
返回(成功!=错误);
/*---------------------------*/
#elif(复制方法==2)
/*---------------------------*/
如果(QFile::exists(outputFile))
{
QFile::删除(outputFile);
}
发射状态更新(0);
QFile src(源文件);
const bool success=src.copy(outputFile);
发射状态更新(100);
如果(!成功)
{
emit messageLogged(QString(“未能复制文件:%1”).arg(src.errorString());
}
回归成功;
/*---------------------------*/
#否则
/*---------------------------*/
#错误:指定了无效的复制方法!
/*---------------------------*/
#endif//COPY\u方法
/*---------------------------*/
}
方法#0是我最初做的。一旦我这样做,文件被复制到的目录(而不是文件本身!)将在以后变得“不可删除”。这是可复制的。而且,只要我使用方法1或方法2,问题就解决了

在第一篇文章中,我说这种情况很少发生。是的,因为(通常)函数“some_function”很少被调用。但是当调用这个函数时(或者当我强制调用它时),问题总是会发生,至少只要我仍然使用copy方法#0

最后,当目录不能被删除时,系统返回的错误是非常不明确的“拒绝访问”(Win32错误0x5),因此这没有多大帮助。如果确实发生,则问题会出现在RemoveDirectoy()函数以及QDir::rmdir()方法中。目录是空的


~更新#2~

好的,下面是一个完整的例子,改编自Harry Johnston提供的代码:

#include <Windows.h>
#include <stdio.h>

int main(int argc, char ** argv)
{
    if(!CreateDirectoryW(L"C:\\Users\\MuldeR\\AppData\\Local\\Temp\\umTpRwui9MpP", NULL))
    {
        printf("CreateDirectory Failed: Error %u\n", GetLastError());
        return 1;
    }

    const wchar_t *const sourceFile = L"C:\\Windows\\Media\\ding.wav\0";
    const wchar_t *const outputFile = L"C:\\Users\\MuldeR\\AppData\\Local\\Temp\\umTpRwui9MpP\\test.wav\0";

    SHFILEOPSTRUCTW fileOperation;
    memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));

    fileOperation.wFunc = FO_COPY;
    fileOperation.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_FILESONLY;
    fileOperation.pFrom = sourceFile;
    fileOperation.pTo = outputFile;

    int result = SHFileOperationW(&fileOperation);
    if (result != 0)
    {
        printf("SHFileOperation Failed: Error%u\n", result);
        return 1;
    }

    if(!DeleteFileW(outputFile))
    {
        printf("DeleteFile Failed: Error %u\n", GetLastError());
        return 1;
    }

    if (!RemoveDirectoryW(L"C:\\Users\\MuldeR\\AppData\\Local\\Temp\\umTpRwui9MpP"))
    {
        printf("RemoveDirectory Failed: Error %u\n", GetLastError());
        return 1;
    }

    printf("OK\n");
    return 0;
}
#包括
#包括
int main(int argc,字符**argv)
{
如果(!CreateDirectoryW(L“C:\\Users\\MuldeR\\AppData\\Local\\Temp\\umTpRwui9MpP”,NULL))
{
printf(“CreateDirectory失败:错误%u\n”,GetLastError());
返回1;
}
康斯特沃克哈特酒店
c:\windows\media\desktop.ini
#include <Windows.h>
#include <stdio.h>

#define target L"C:\\Users\\MuldeR\\AppData\\Local\\Temp\\umTpRwui9MpP"

int main(int argc, char ** argv)
{
    if(!CreateDirectoryW(target, NULL))
    {
        printf("CreateDirectory Failed: Error %u\n", GetLastError());
        return 1;
    }

    const wchar_t *const sourceFile = L"C:\\Windows\\Media\\ding.wav\0";
    const wchar_t *const outputFile = target L"\\test.wav\0";

    SHFILEOPSTRUCTW fileOperation;
    memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));

    fileOperation.wFunc = FO_COPY;
    fileOperation.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_FILESONLY;
    fileOperation.pFrom = sourceFile;
    fileOperation.pTo = outputFile;

    int result = SHFileOperationW(&fileOperation);
    if (result != 0)
    {
        printf("SHFileOperation Failed: Error%u\n", result);
        return 1;
    }

    if(!DeleteFileW(outputFile))
    {
        printf("DeleteFile(outputFile) Failed: Error %u\n", GetLastError());
        return 1;
    }

    if (!DeleteFileW(target L"\\desktop.ini"))
    {
        printf("DeleteFile(desktop.ini) Failed: Error %u\n", GetLastError());
        return 1;
    }

    if (!SetFileAttributes(target, 0))
    {
        printf("SetFileAttributes Failed: Error %u\n", GetLastError());
        return 1;
    }

    if (!RemoveDirectoryW(target))
    {
        printf("RemoveDirectory Failed: Error %u\n", GetLastError());
        return 1;
    }

    printf("OK\n");
    return 0;
}
#include <Windows.h>
#include <stdio.h>

#define target L"C:\\Users\\MuldeR\\AppData\\Local\\Temp\\umTpRwui9MpP"

int main(int argc, char ** argv)
{
    if(!CreateDirectoryW(target, NULL))
    {
        printf("CreateDirectory Failed: Error %u\n", GetLastError());
        return 1;
    }

    const wchar_t *const sourceFile = L"C:\\Windows\\Media\\ding.wav\0";
    const wchar_t *const outputFile = target L"\\test.wav\0";

    SHFILEOPSTRUCTW fileOperation;
    memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));

    fileOperation.wFunc = FO_COPY;
    fileOperation.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_FILESONLY;
    fileOperation.pFrom = sourceFile;
    fileOperation.pTo = outputFile;

    int result = SHFileOperationW(&fileOperation);
    if (result != 0)
    {
        printf("SHFileOperation Failed: Error%u\n", result);
        return 1;
    }

    memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));

    fileOperation.wFunc = FO_DELETE;
    fileOperation.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
    fileOperation.pFrom = target L"\0";

    result = SHFileOperationW(&fileOperation);
    if (result != 0)
    {
        printf("SHFileOperation Failed: Error%u\n", result);
        return 1;
    }

    printf("OK\n");
    return 0;
}