public void TestVoidFunc() { HashSet <string> recordedMembers = new HashSet <string>(); HashSet <string> compiledMembers = new HashSet <string>(); var cachedPath = "Assets/Mods/CapsLua/LuaPrecompile/MemberList.txt"; //var cachedPath = "EditorOutput/LuaPrecompile/CachedCommands.txt"; if (PlatDependant.IsFileExist(cachedPath)) { try { using (var sr = PlatDependant.OpenReadText(cachedPath)) { while (true) { var line = sr.ReadLine(); if (line == null) { break; } if (!string.IsNullOrEmpty(line)) { recordedMembers.Add(line); } } } } catch (Exception e) { PlatDependant.LogError(e); } } }
public static void LogError(this IntPtr l, object message) { PushLuaStackTrace(l); var lstack = l.tostring(-1); l.pop(1); var m = (message ?? "nullptr").ToString() + "\n" + lstack; PlatDependant.LogError(m); }
public static void ReinitGlobalLuaInEditor() { if (!Application.isPlaying) { ReinitGlobalLua(); } else { PlatDependant.LogError("Cannot reinit global lua while playing."); } }
public static void TestPack <TLuaPack>() where TLuaPack : struct, ILuaPack { var l = GlobalLua.L.L; TLuaPack pin = default; TLuaPack pout = default; l.CallGlobal("TestPack", pin, out pout); for (int i = 0; i < pout.ElementCount; ++i) { PlatDependant.LogError(pout[i]); } }
public static void TestLua() { UnityEditor.AssetDatabase.OpenAsset(UnityEditor.AssetDatabase.LoadMainAssetAtPath(ResManager.__ASSET__), ResManager.__LINE__); var l = GlobalLua.L.L; using (var lr = l.CreateStackRecover()) { l.pushnumber(250); string str; l.CallGlobal(out str, "dump", LuaPack.Pack(l.OnStack(-1))); PlatDependant.LogError(str); } }
internal static void DisposeObj(IntPtr handle) { if (handle != IntPtr.Zero) { try { var gchandle = (GCHandle)handle; gchandle.Free(); } catch (Exception e) { PlatDependant.LogError(e); } } }
public int TestReturnOutFunc(string filePath, int times, out string rv) { string last = null; for (int i = 0; i < times; ++i) { if (i == 3) { rv = i.ToString(); return(i); } HashSet <string> recordedMembers = new HashSet <string>(); HashSet <string> compiledMembers = new HashSet <string>(); var cachedPath = filePath + i; //var cachedPath = "EditorOutput/LuaPrecompile/CachedCommands.txt"; if (PlatDependant.IsFileExist(cachedPath)) { try { using (var sr = PlatDependant.OpenReadText(cachedPath)) { while (true) { var line = sr.ReadLine(); if (line == null) { break; } last = line; if (!string.IsNullOrEmpty(line)) { recordedMembers.Add(line); } } } } catch (Exception e) { PlatDependant.LogError(e); rv = e.Message; return(i); } } } rv = last; return(last?.Length ?? 0); }
public static T GetContainer <T>() where T : class { var handle = NativeImported.GetThreadLocalContainer(); if (handle != IntPtr.Zero) { object obj = null; try { obj = ((GCHandle)handle).Target; } catch (Exception e) { PlatDependant.LogError(e); } return(obj as T); } return(null); }
public void TestParamFunc(string filePath, int times) { for (int i = 0; i < times; ++i) { HashSet <string> recordedMembers = new HashSet <string>(); HashSet <string> compiledMembers = new HashSet <string>(); var cachedPath = filePath + i; //var cachedPath = "EditorOutput/LuaPrecompile/CachedCommands.txt"; if (PlatDependant.IsFileExist(cachedPath)) { try { using (var sr = PlatDependant.OpenReadText(cachedPath)) { while (true) { var line = sr.ReadLine(); if (line == null) { break; } if (!string.IsNullOrEmpty(line)) { recordedMembers.Add(line); } } } } catch (Exception e) { PlatDependant.LogError(e); } } } }
public static void LogError(object obj) { PlatDependant.LogError(obj); }
public static TaskProgress MakeZipBackground(string zipFile, string srcDir, IList <string> entries, System.Threading.EventWaitHandle waithandle) { return(PlatDependant.RunBackground(progress => { try { if (string.IsNullOrEmpty(zipFile) || entries == null || entries.Count == 0 || !System.IO.Directory.Exists(srcDir)) { return; } progress.Total = entries.Count; using (var stream = PlatDependant.OpenWrite(zipFile)) { using (var zip = new ZipArchive(stream, ZipArchiveMode.Create)) { if (!srcDir.EndsWith("/") && !srcDir.EndsWith("\\")) { srcDir += "/"; } for (int i = 0; i < entries.Count; ++i) { progress.Length = i; var entry = entries[i]; if (string.IsNullOrEmpty(entry)) { continue; } var src = srcDir + entry; if (PlatDependant.IsFileExist(src)) { try { using (var srcstream = PlatDependant.OpenRead(src)) { var zentry = zip.CreateEntry(entry.Replace('\\', '/')); using (var dststream = zentry.Open()) { srcstream.CopyTo(dststream); } } } catch (Exception e) { PlatDependant.LogError("zip entry FAIL! " + entry); PlatDependant.LogError(e); } } } } } } catch (Exception e) { PlatDependant.LogError("Build zip FAIL! " + zipFile); PlatDependant.LogError(e); } finally { if (waithandle != null) { waithandle.Set(); } } })); }
public static void MakeObb(string dest, params string[] subzips) { if (!string.IsNullOrEmpty(dest) && subzips != null && subzips.Length > 0) { HashSet <string> reskeys = new HashSet <string>(); HashSet <string> sptkeys = new HashSet <string>(); using (var sdest = PlatDependant.OpenWrite(dest)) { using (var zdest = new ZipArchive(sdest, ZipArchiveMode.Create)) { for (int i = 0; i < subzips.Length; ++i) { try { var sfile = subzips[i]; if (PlatDependant.IsFileExist(sfile)) { var key = System.IO.Path.GetFileNameWithoutExtension(sfile).ToLower(); bool isres = false; bool isspt = false; HashSet <string> entrynames = new HashSet <string>(); using (var ssrc = PlatDependant.OpenRead(sfile)) { using (var zsrc = new ZipArchive(ssrc, ZipArchiveMode.Read)) { foreach (var sentry in zsrc.Entries) { var fullname = sentry.FullName; if (fullname.StartsWith("res/")) { isres = true; } else if (fullname.StartsWith("spt/")) { isspt = true; } if (entrynames.Add(fullname)) { var dentry = zdest.CreateEntry(fullname, isres ? CompressionLevel.NoCompression : CompressionLevel.Optimal); using (var ses = sentry.Open()) { using (var des = dentry.Open()) { ses.CopyTo(des); } } } } } } if (isres) { reskeys.Add(key); } if (isspt) { sptkeys.Add(key); } } } catch (Exception e) { PlatDependant.LogError(e); } } if (reskeys.Count > 0) { var resindex = zdest.CreateEntry("res/index.txt", CompressionLevel.Optimal); using (var sindex = resindex.Open()) { using (var swindex = new System.IO.StreamWriter(sindex, System.Text.Encoding.UTF8)) { foreach (var key in reskeys) { swindex.WriteLine(key); } } } } if (sptkeys.Count > 0) { var sptindex = zdest.CreateEntry("spt/index.txt", CompressionLevel.Optimal); using (var sindex = sptindex.Open()) { using (var swindex = new System.IO.StreamWriter(sindex, System.Text.Encoding.UTF8)) { foreach (var key in sptkeys) { swindex.WriteLine(key); } } } } } } } }
public static System.IO.Stream GetLuaStream(string name, out string location) { #if UNITY_EDITOR try { if (!string.IsNullOrEmpty(name)) { if (name.Length > 0 && name[0] == '?') { var real = name.Substring("?raw.".Length); string mod = null; string norm = real; if (real.StartsWith("mod.")) { if (real.StartsWith("mod.\"")) { var mindex = real.IndexOf('\"', "mod.\"".Length); if (mindex > 0) { mod = real.Substring("mod.\"".Length, mindex - "mod.\"".Length); norm = real.Substring(mindex + 2); } } else { var mindex = real.IndexOf('.', "mod.".Length); if (mindex > 0) { mod = real.Substring("mod.".Length, mindex - "mod.".Length); norm = real.Substring(mindex + 1); } } } norm = norm.Replace('.', '/'); bool isFileExist = false; if (mod == null) { real = "Assets/CapsSpt/" + norm + ".lua"; } else { string package; ResManager.EditorResLoader.ResRuntimeCache.ModToPackage.TryGetValue(mod, out package); if (!string.IsNullOrEmpty(package)) { real = "Packages/" + package + "/CapsSpt/" + norm + ".lua"; //real = EditorToClientUtils.GetPathFromAssetName(real); isFileExist = !string.IsNullOrEmpty(real) && PlatDependant.IsFileExist(real); } if (!isFileExist) { real = "Assets/Mods/" + mod + "/CapsSpt/" + norm + ".lua"; } } if (isFileExist || PlatDependant.IsFileExist(real)) { location = real; return(PlatDependant.OpenRead(real)); } } else { var file = "CapsSpt/" + name.Replace('.', '/') + ".lua"; string found; if (ThreadLocalObj.GetThreadId() == ThreadSafeValues.UnityThreadID) { found = ResManager.EditorResLoader.CheckDistributePath(file, true); } else { found = ResManager.EditorResLoader.CheckDistributePathSafe(file); } //if (found != null) //{ // if (found.StartsWith("Packages/")) // { // found = EditorToClientUtils.GetPathFromAssetName(found); // } //} if (found != null) { location = found; return(PlatDependant.OpenRead(found)); } } } } catch (Exception e) { PlatDependant.LogError(e); } #elif UNITY_ENGINE || UNITY_5_3_OR_NEWER try { if (name.Length > 0 && name[0] == '?') { if (name.StartsWith("?raw.")) { if (_RuntimeRawManifest != null) { var real = name.Substring("?raw.".Length); real = real.Replace("\"", ""); string archreal = Environment.Is64BitProcess ? "@64." + real : "@32." + real; CapsResManifestNode node; if (_RuntimeRawManifest.TryGetItemIgnoreExt(archreal, out node, _LuaRequireSeperateChars) || _RuntimeRawManifest.TryGetItemIgnoreExt(real, out node, _LuaRequireSeperateChars)) { if (node != null && node.Item != null) { var item = node.Item; while (item.Ref != null) { item = item.Ref; } return(GetLuaStream(item, out location)); } } } } } else { if (_RuntimeManifest != null) { var node = _RuntimeManifest.GetItem(name, _LuaRequireSeperateChars); if (node != null && node.Item != null) { var item = node.Item; while (item.Ref != null) { item = item.Ref; } return(GetLuaStream(item, out location)); } } } } catch (Exception e) { PlatDependant.LogError(e); } #else try { if (!string.IsNullOrEmpty(name)) { if (name.Length > 0 && name[0] == '?') { var real = name.Substring("?raw.".Length); string mod = null; string norm = real; if (real.StartsWith("mod.")) { if (real.StartsWith("mod.\"")) { var mindex = real.IndexOf('\"', "mod.\"".Length); if (mindex > 0) { mod = real.Substring("mod.\"".Length, mindex - "mod.\"".Length); norm = real.Substring(mindex + 2); } } else { var mindex = real.IndexOf('.', "mod.".Length); if (mindex > 0) { mod = real.Substring("mod.".Length, mindex - "mod.".Length); norm = real.Substring(mindex + 1); } } } norm = norm.Replace('.', '/'); if (mod == null) { real = "/spt/" + norm + ".lua"; } else { real = "/mod/" + mod + "/spt/" + norm + ".lua"; } var stream = ResManager.LoadFileRelative(real); if (stream != null) { location = real; return(stream); } } else { var file = "/spt/" + name.Replace('.', '/') + ".lua"; string real, mod, dist; real = ResManager.FindFile(file, out mod, out dist); if (real != null) { try { var stream = PlatDependant.OpenRead(real); if (stream != null) { location = file; if (!string.IsNullOrEmpty(dist)) { location = "/dist/" + dist + location; } if (!string.IsNullOrEmpty(mod)) { location = "/mod/" + mod + location; } return(stream); } } catch (Exception e) { PlatDependant.LogError(e); } } } } } catch (Exception e) { PlatDependant.LogError(e); } #endif location = ""; return(null); }
private static System.IO.Stream GetLuaStream(CapsResManifestItem item, out string location) { try { var rnode = item.Node; System.Text.StringBuilder sbpath = new System.Text.StringBuilder(); while (rnode.Parent != null) { if (sbpath.Length > 0) { sbpath.Insert(0, '/'); } sbpath.Insert(0, rnode.PPath); rnode = rnode.Parent; } var path = sbpath.ToString(); // load from update path var sptpath = ThreadSafeValues.UpdatePath + "/spt/" + path; if (PlatDependant.IsFileExist(sptpath)) { location = sptpath; return(PlatDependant.OpenRead(sptpath)); } // load from package if (ThreadSafeValues.AppStreamingAssetsPath.Contains("://")) { if (ThreadSafeValues.AppPlatform == RuntimePlatform.Android.ToString() && ResManager.LoadAssetsFromApk) { // Obb if (ResManager.LoadAssetsFromObb && ResManager.ObbZipArchive != null) { sptpath = "spt/" + path; int retryTimes = 10; for (int i = 0; i < retryTimes; ++i) { Exception error = null; do { ZipArchive za = ResManager.ObbZipArchive; if (za == null) { PlatDependant.LogError("Obb Archive Cannot be read."); break; } try { var entry = za.GetEntry(sptpath); if (entry != null) { location = sptpath; return(entry.Open()); } } catch (Exception e) { error = e; break; } } while (false); if (error != null) { if (i == retryTimes - 1) { PlatDependant.LogError(error); } else { PlatDependant.LogError(error); PlatDependant.LogInfo("Need Retry " + i); } } else { break; } } } // Apk //if (true) { sptpath = "assets/spt/" + path; int retryTimes = 10; for (int i = 0; i < retryTimes; ++i) { Exception error = null; do { ZipArchive za = ResManager.AndroidApkZipArchive; if (za == null) { PlatDependant.LogError("Apk Archive Cannot be read."); break; } try { var entry = za.GetEntry(sptpath); if (entry != null) { location = sptpath; return(entry.Open()); } } catch (Exception e) { error = e; break; } } while (false); if (error != null) { if (i == retryTimes - 1) { PlatDependant.LogError(error); } else { PlatDependant.LogError(error); PlatDependant.LogInfo("Need Retry " + i); } } else { break; } } } } } else { sptpath = ThreadSafeValues.AppStreamingAssetsPath + "/spt/" + path; if (PlatDependant.IsFileExist(sptpath)) { location = sptpath; return(PlatDependant.OpenRead(sptpath)); } } } catch (Exception e) { PlatDependant.LogError(e); } location = ""; return(null); }
private static void LoadRuntimeManifest(TaskProgress progress) { try { var maniPath = ThreadSafeValues.UpdatePath + "/spt/manifest.m.txt"; if (PlatDependant.IsFileExist(maniPath)) { _RuntimeRawManifest = LoadManifest(maniPath); } else { CapsResManifest mani = new CapsResManifest(); // load from update path var sptfolder = ThreadSafeValues.UpdatePath + "/spt/"; try { var files = PlatDependant.GetAllFiles(sptfolder); if (files != null && files.Length > 0) { for (int i = 0; i < files.Length; ++i) { var file = files[i]; var part = file.Substring(sptfolder.Length).Replace('\\', '/'); var node = mani.AddOrGetItem(part); if (node.Item == null) { CapsResManifestItem item; item = new CapsResManifestItem(node); node.Item = item; } } } } catch (Exception e) { PlatDependant.LogError(e); } // load from package if (ThreadSafeValues.AppStreamingAssetsPath.Contains("://")) { if (ThreadSafeValues.AppPlatform == RuntimePlatform.Android.ToString() && ResManager.LoadAssetsFromApk) { // Obb if (ResManager.LoadAssetsFromObb && ResManager.ObbZipArchive != null) { sptfolder = "spt/"; int retryTimes = 10; int entryindex = 0; for (int i = 0; i < retryTimes; ++i) { Exception error = null; do { ZipArchive za = ResManager.ObbZipArchive; if (za == null) { PlatDependant.LogError("Obb Archive Cannot be read."); break; } try { var entries = za.Entries; while (entryindex < entries.Count) { var entry = entries[entryindex]; var fullname = entry.FullName; if (fullname.StartsWith(sptfolder)) { var part = fullname.Substring(sptfolder.Length); var node = mani.AddOrGetItem(part); if (node.Item == null) { CapsResManifestItem item; item = new CapsResManifestItem(node); node.Item = item; } } ++entryindex; } } catch (Exception e) { error = e; break; } } while (false); if (error != null) { if (i == retryTimes - 1) { PlatDependant.LogError(error); } else { PlatDependant.LogError(error); PlatDependant.LogInfo("Need Retry " + i); } } else { break; } } } // Apk //if (true) { sptfolder = "assets/spt/"; int retryTimes = 10; int entryindex = 0; for (int i = 0; i < retryTimes; ++i) { Exception error = null; do { ZipArchive za = ResManager.AndroidApkZipArchive; if (za == null) { PlatDependant.LogError("Apk Archive Cannot be read."); break; } try { var entries = za.Entries; while (entryindex < entries.Count) { var entry = entries[entryindex]; var fullname = entry.FullName; if (fullname.StartsWith(sptfolder)) { var part = fullname.Substring(sptfolder.Length); var node = mani.AddOrGetItem(part); if (node.Item == null) { CapsResManifestItem item; item = new CapsResManifestItem(node); node.Item = item; } } ++entryindex; } } catch (Exception e) { error = e; break; } } while (false); if (error != null) { if (i == retryTimes - 1) { PlatDependant.LogError(error); } else { PlatDependant.LogError(error); PlatDependant.LogInfo("Need Retry " + i); } } else { break; } } } } } else { sptfolder = ThreadSafeValues.AppStreamingAssetsPath + "/spt/"; try { var files = PlatDependant.GetAllFiles(sptfolder); if (files != null && files.Length > 0) { for (int i = 0; i < files.Length; ++i) { var file = files[i]; var part = file.Substring(sptfolder.Length).Replace('\\', '/'); var node = mani.AddOrGetItem(part); if (node.Item == null) { CapsResManifestItem item; item = new CapsResManifestItem(node); node.Item = item; } } } } catch (Exception e) { PlatDependant.LogError(e); } } mani.TrimExcess(); _RuntimeRawManifest = mani; _RuntimeManifestReady.Set(); SaveManifest(mani, maniPath); } } finally { _RuntimeManifestReady.Set(); _RuntimeManifestTaskIdle.Set(); } }
public static bool BuildResUpdate(string oldz, string newz, string diff) { LinkedList<IDisposable> lstToDispose = new LinkedList<IDisposable>(); try { ZipArchive olda = null, newa = null, diffa = null; try { var olds = File.OpenRead(oldz); lstToDispose.AddFirst(olds); olda = new ZipArchive(olds, ZipArchiveMode.Read); lstToDispose.AddFirst(olda); } catch { } try { var news = File.OpenRead(newz); lstToDispose.AddFirst(news); newa = new ZipArchive(news, ZipArchiveMode.Read); lstToDispose.AddFirst(newa); } catch { } HashSet<string> diffb = new HashSet<string>(); if (newa == null) { return false; } else if (Path.GetFileNameWithoutExtension(oldz) != Path.GetFileNameWithoutExtension(newz)) { PlatDependant.LogError("Build update diff error - the old zip and new zip have different names."); return false; } else { string mentry = "res/mani/" + Path.GetFileNameWithoutExtension(newz).ToLower() + ".m.ab"; CapsResManifest mold = null; CapsResManifest mnew = null; // get mani of old try { if (olda != null) { var oldme = olda.GetEntry(mentry); if (oldme != null) { using (var stream = oldme.Open()) { using (var mems = new MemoryStream()) { stream.CopyTo(mems); var mab = UnityEngine.AssetBundle.LoadFromMemory(mems.ToArray()); if (mab) { var allassets = mab.LoadAllAssets<CapsResOnDiskManifest>(); if (allassets != null && allassets.Length > 0) { mold = CapsResManifest.Load(allassets[0]); } mab.Unload(true); } } } } } } catch { } // get mani of new try { var newme = newa.GetEntry(mentry); if (newme != null) { using (var stream = newme.Open()) { using (var mems = new MemoryStream()) { stream.CopyTo(mems); var mab = UnityEngine.AssetBundle.LoadFromMemory(mems.ToArray()); if (mab) { var allassets = mab.LoadAllAssets<CapsResOnDiskManifest>(); if (allassets != null && allassets.Length > 0) { mnew = CapsResManifest.Load(allassets[0]); } mab.Unload(true); } } } } } catch { } string abrootold = "res/"; string umpathold = "res/res"; if (mold != null && !string.IsNullOrEmpty(mold.MFlag)) { abrootold += "mod/" + mold.MFlag + "/"; umpathold = abrootold + mold.MFlag; } string abrootnew = "res/"; string umpathnew = "res/res"; if (mnew != null && !string.IsNullOrEmpty(mnew.MFlag)) { abrootnew += "mod/" + mnew.MFlag + "/"; umpathnew = abrootnew + mnew.MFlag; } // parse old manifest UnityEngine.AssetBundleManifest maniold = null; try { if (olda != null) { var emani = olda.GetEntry(umpathold); if (emani != null) { using (var smani = emani.Open()) { using (var mems = new MemoryStream()) { smani.CopyTo(mems); var resab = UnityEngine.AssetBundle.LoadFromMemory(mems.ToArray()); if (resab) { var allassets = resab.LoadAllAssets<UnityEngine.AssetBundleManifest>(); if (allassets != null && allassets.Length > 0) { maniold = allassets[0]; if (maniold) { maniold = Object.Instantiate(maniold); } } resab.Unload(true); } } } } } } catch { } // parse new manifest UnityEngine.AssetBundleManifest maninew = null; try { var emani = newa.GetEntry(umpathnew); if (emani != null) { using (var smani = emani.Open()) { using (var mems = new MemoryStream()) { smani.CopyTo(mems); var resab = UnityEngine.AssetBundle.LoadFromMemory(mems.ToArray()); if (resab) { var allassets = resab.LoadAllAssets<UnityEngine.AssetBundleManifest>(); if (allassets != null && allassets.Length > 0) { maninew = allassets[0]; if (maninew != null) { maninew = Object.Instantiate(maninew); } } resab.Unload(true); } } } } } catch { } // both manifest found? if (maninew == null) { File.Copy(newz, diff, true); return true; } // parse diff assets and bundles if (maninew != null) { var allbundles = maninew.GetAllAssetBundles(); foreach (var bundle in allbundles) { var newe = newa.GetEntry(abrootnew + bundle); if (newe == null) { continue; } if (maniold != null && maninew.GetAssetBundleHash(bundle) == maniold.GetAssetBundleHash(bundle)) { if (olda != null) { var olde = olda.GetEntry(abrootold + bundle); if (olde != null) { if (olde.Length == newe.Length) { // TODO: sometimes the AssetBundleHash may be same (example: we deleted a sprite-atlas). // we can diff these from: AssetBundle TypeTreeHash. we should load bundle.manifest and parse it use YAML. it's so difficult. // or we can get the ab file's change time. but this information is not recorded to zip // or we can get the crc of the entry. but it's private. // or we can get md5 of the entry. but need full read. // so we choose use length. In this condition, the ab file length's diff is almost a must. continue; } } } } diffb.Add(bundle); } } // create update zip if (diffb.Count > 0) { try { var streama = PlatDependant.OpenWrite(diff); if (streama != null) { lstToDispose.AddFirst(streama); diffa = new ZipArchive(streama, ZipArchiveMode.Create); if (diffa != null) { lstToDispose.AddFirst(diffa); // each bundle foreach (var bundle in diffb) { try { var ename = abrootnew + bundle; var entryn = newa.GetEntry(ename); if (entryn != null) { var entryd = diffa.CreateEntry(ename, CompressionLevel.Optimal); if (entryd != null) { using (var streamn = entryn.Open()) { using (var streamd = entryd.Open()) { streamn.CopyTo(streamd); } } } } } catch { } } // mani / unity manifest / version.txt string[] rawcopyentries = new[] { mentry, umpathnew, "res/version.txt" }; for (int i = 0; i < rawcopyentries.Length; ++i) { var ename = rawcopyentries[i]; try { var entrys = newa.GetEntry(ename); if (entrys != null) { var entryd = diffa.CreateEntry(ename, CompressionLevel.Optimal); if (entryd != null) { using (var streams = entrys.Open()) { using (var streamd = entryd.Open()) { streams.CopyTo(streamd); } } } } } catch { } } } } } catch { } return true; } } } catch { } finally { foreach (var dis in lstToDispose) { if (dis != null) { dis.Dispose(); } } } return false; }