//io 文件相关 namespace builtin; self.io = global.io; namespace io; ::Shell32 = ..raw.loadDll("Shell32.dll") getSpecial = function(id,...){ var r = {WORD v[0x208/*_MAX_PATH_U16*/]} if ( 0 <= ::Shell32.SHGetFolderPath(null,id,null,0,r) ){ return joinpath(r.v,...); } } getSize = function(path){ var f = open(path,"rb"); if( f ){ var r = f.size(); f.close(); return r; } } appData = function(p,d){ if(!d) return getSpecial(0x1c /*_CSIDL_LOCAL_APPDATA*/,p); return specialData(p,d,0x1c/*_CSIDL_LOCAL_APPDATA*/); } specialData = function(p,d,id){ p = getSpecial(id,p); if(d!==null) return updateData(d,p); return p; } updateData = function(d,p,...){ if(...) p = joinpath(p,...); if(d!==null){ var e; var f = open(p,"rb"); if(f){ e = f.size()==#d; if(e && (d[1]+d[2]==0xA7) ){ var a = ..raw.convert(d,{INT v},60).v + 8; f.seek("set",a); e = f.read({INT v})[["v"]]===..raw.convert(d,{INT v},a).v; } f.close(); } if(!e && ! ..string.save(p,d) ) return exist(p); } return p; } var tmpdir = ..string.expand("%TMP%") : appData("Temp") ; ..string.setenv("TMP",tmpdir); var tempId,tempTick = 0; tmpname = function(p,e){ d = joinpath(tmpdir,"\"); var tk = ..time.tick(); if(tk == tempTick) tempId++; else{ tempId = 0; tempTick = tk; } var t = ..string.format("%s$%X$%X",(p:"") ++ (tempId:""),..thread.getId(),tk); if(!e) e = ""; var r; var i = 0; do{ r = ..io.joinpath(d, t ++ (i||"") ++ e) i++; }while(exist(r)) return r; } curDir = lambda(dir) !dir ? ..io.fullpath("./") : ::Kernel32.SetCurrentDirectoryB( fullpath(dir) ); if(_WIN10_LATER) { if( _WIN_VER_MAJOR > 10 || _WIN_VER_MINOR > 0 || _WIN_VER_BUILD >= 16299 ){ self.utf8 = true; //if(::Kernel32.GetACP()==65001) io.utf8 = true; } } file.write = function(p,...){ var f,e,c,r = file(p,"w+b"); if(f){ r,e,c = f.write(...); f.close(); } return r,e,c; } file.read = ..string.load; writeFile = file.write;//@Deprecated write = writeFile; //@Deprecated readFile = file.read; //@Deprecated read = readFile; //@Deprecated /**intellisense(io) getSpecial(_CSIDL__) = 获取特殊文件夹,\n参数@1使用 _CSIDL 开头的常量指定特殊文件夹的 CSIDL,\n不指定参数@1则默认值为 _CSIDL_DESKTOP,\n可选增加任意个拼接到目录后的子路径参数\n这个函数与fsys.getSpecial函数用法接近,\n但支持不定个数子路径参数, 不支持返回PIDL\n\nfsys.knownFolder 可用于获取更多已知的特殊文件夹 appData( = 获取 %LocalAppData% 目录下的绝对路径。\n可选使用指定需要存入的数据 appData(.(path,data) = 将@path指定的相对路径转换为系统 %LocalAppData% 目录下的绝对路径,\n可选使用 @data 指定需要存入的数据,\n存入文件与目标文件长度不同或 PE 时间戳不同则允许替换旧文件,\n指定 @data 参数后如果无法创建文件返回null,\n最后返回转换所得的完整路径 specialData(.(path,data,csidl) = 将 @path 指定的相对路径转换为特殊文件夹下的绝对路径,\n可选使用 @data 指定需要存入的数据,\n存入文件与目标文件长度不同或 PE 时间戳不同则允许替换旧文件,\n指定 @data 参数后如果无法创建文件返回null,\n参数@csidl 使用 _CSIDL 开头的常量指定特殊文件夹的 CSIDL,\n不指定@csidl 则默认值为 _CSIDL_DESKTOP,\n最后返回转换所得的完整路径 updateData( = 更新指定文件的数据 updateData(.(data,path,->->->) = 更新指定 @path 指定路径的文件为 @data 指定的数据。\n如果添加更多参数,则首先调用 io.joinpath 拼接到 @path 后面。\n存入文件与目标文件长度不同或 PE 时间戳不同则允许替换旧文件。\n替换失败返回 null,否则返回文件路径 getSize(__) = 获取参数@1指定路径的文件字节长度,\n返回数值 curDir( = 获取或修改当前目录 curDir(.() = 无参数获取当前目录 curDir(.(dir) = 将 @dir 参数指定的目录路径转换为完整路径并设为当前目录\n成功返回 true tmpname( = 生成系统临时文件目录下的临时文件路径。\n此函数不会生成实际的文件,即使密集调用也不会生成相同的文件名。 tmpname(.(prefix,ext) = 生成临时文件路径,\n可选用 @prefix 参数指定前缀名,\n可选用 @ext 参数指定后缀名,后缀名应包含点 file.write(.(path,->->->) = 以二进制模式创建或打开文件并写入数据(清空原数据)。\n\n参数 @1 指定要写入的文件路径。\n其他一个或多个参数指定要写入的数据(可指定字符串,数值,buffer,或结构体)。\n成功返回 true,失败返回 null,错误信息,错误代码。\n\nstring.save 函数作用类似但仅支持单个参数(只能是字符串或 buffer 类型)。\n另外,string.save 将参数 @2 设为 true 可以追加而不清空数据。 file.read(__/*文件路径*/) = string.load 函数的别名。\n以二进制模式读取文件或内嵌资源文件,返回普通字符串。\n\n路径开始可用单斜杠(或单反斜杠)表示应用程序根目录,前面再加`~`表示 EXE 根目录。\n如果`~\`或`~/`开头的EXE根目录路径不存在,自动转换为应用程序根目录下的路径重试。 end intellisense**/ /**intellisense(::) ::Shell32 = 默认已加载的Shell32.dll模块对象(参考标准库:peload.io),\n提供Windows系统外壳 API ::Shell32.api("__/*输入函数名字*/","void()" ) = 声明Kernel32 API函数 ::Shell32.SHChangeNotify(_SHCNE__,0,0,0) = 通知操作系统外壳刷新,例如刷新桌面图标等\n参数依次为@eventId,@flags,@item1,@item2\n参数@flags的值为5时函数名必须加上 W 尾标,即 ::Shell32.SHChangeNotifyW ::Shell32.ShellExecute(.(hwnd,operation,path,param,workDir,cmdShow) = 执行 path 指定的程序,\n第一个参数为数值格式的句柄,\n最后一个参数为数值,指定为1即可,其他参数都是字符串,\n详细用法请参考该 API 文档,\n注意省略的参数也要指定 null 值,\n非声明式调用 API 不能减少参数个数,\nraw.execute 函数提供类似功能,但所有参数都可以省略。\nprocess.execute 函数也提供类似功能 ::Shell32.Control_RunDLL(.(hwnd,hinst,cmdLine,cmdShow) = 可用于启动控制面板命令,\nhwnd可指定为0,hinst 可指定为 _HINSTANSE,\ncmdLine 指定启动参数,cmdShow 指定为1即可,\n也可以通过process.rundll 运行此函数,\n或通过 process.control 直接执行控制面板命令 ::Shell32.? = 可不用声明直接在此输入函数名并调用API函数\n\n一、传入参数规则:\n1、null参数不可省略\n2、32位整数类型,小于32位的整数、以及枚举类型都可以直接在API参数中写数值。\n3、对于任何数值类型的指针(输出参数)一律使用结构体表示,例如double * v 表示为{ double v }\n4、数组使用结构体表示\n5、所有结构体传给API的都是指针地址,都是输出参数并增加返回值\n\n二、返回值规则:\n1、返回值默认为int类型\n2、可以使用[API尾标]改变返回值为其他类型\n\n三、所有可用的【API尾标】:\n::Shell32.ApiNameW() 切换到Unicode版本,字符串UTF8-UTF16双向转换\n::Shell32.ApiNameA() 切换到ANSI版本,字符串不作任何转换\n::Shell32.ApiNameL() 返回值为64位LONG类型\n::Shell32.ApiNameP() 返回值为指针类型\n::Shell32.ApiNameD() 返回值为double浮点数\n::Shell32.ApiNameF() 返回值为float浮点数\n::Shell32.ApiNameB() 返回值为C++中的8位bool类型\n注意【尾标】前必须是小写字母 end intellisense**/