- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
现在,我正在处理这个错误:
An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
它没有调用堆栈,因为没有为抛出它的 DLL 加载模块。我有一个枚举整个注册表并尝试将所有键/值保存到 SQLite 数据库文件的应用程序,作为注册表快照。从某种意义上说,它不是贪心的,如果它无法访问某些 key ,这些 key 将被丢弃,等等:
using Microsoft.Win32;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace RegistryMonitor
{
class Program
{
static void Main(string[] args)
{
GenerateRegistrySnapshot("SnapshotOne.sqlite");
Console.ReadLine();
}
static void GenerateRegistrySnapshot(string filename)
{
File.Delete(filename);
SQLiteConnection.CreateFile(filename);
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;"))
{
connection.Open();
CreateTable(connection);
Stopwatch watch = new Stopwatch();
Console.WriteLine("Started walking the registry into file {0}.", filename);
watch.Start();
transaction = connection.BeginTransaction();
WalkTheRegistryAndPopulateTheSnapshot(connection);
try
{
transaction.Commit();
transaction.Dispose();
}
catch { }
Console.WriteLine("Finished walking the registry and populating the snapshot.");
watch.Stop();
Console.WriteLine("Finished walking the registry in {0} seconds.", watch.Elapsed.TotalSeconds);
connection.Close();
}
}
static void CreateTable(SQLiteConnection connection)
{
SQLiteCommand command = new SQLiteCommand("CREATE TABLE Snapshot (ID INTEGER PRIMARY KEY AUTOINCREMENT, RegistryView INTEGER NULL, Path TEXT NULL, IsKey BOOLEAN NULL, RegistryValueKind INTEGER NULL, ValueName TEXT NULL, Value BLOB NULL, HashValue INTEGER NULL)", connection);
command.ExecuteNonQuery();
}
static SQLiteTransaction transaction = null;
static int insertions = 0;
static object transactionLock = new object();
static void AddEntry(SQLiteConnection connection, RegistryPath path)
{
SQLiteCommand command = new SQLiteCommand("INSERT INTO Snapshot (RegistryView, Path, IsKey, RegistryValueKind, ValueName, Value, HashValue) VALUES (@RegistryView, @Path, @IsKey, @RegistryValueKind, @ValueName, @Value, @HashValue)", connection);
command.Parameters.Add("@RegistryView", DbType.Int32).Value = path.View;
command.Parameters.Add("@Path", DbType.String).Value = path.Path;
command.Parameters.Add("@IsKey", DbType.Boolean).Value = path.IsKey;
command.Parameters.Add("@RegistryValueKind", DbType.Int32).Value = path.ValueKind;
command.Parameters.Add("@ValueName", DbType.String).Value = path.ValueName;
command.Parameters.Add("@Value", DbType.Object).Value = path.Value;
command.Parameters.Add("@HashValue", DbType.Int32).Value = path.HashValue;
command.ExecuteNonQuery();
lock (transactionLock)
{
insertions++;
if (insertions > 100000)
{
insertions = 0;
transaction.Commit();
transaction.Dispose();
transaction = connection.BeginTransaction();
}
}
}
private static void WalkTheRegistryAndPopulateTheSnapshot(SQLiteConnection connection)
{
List<ManualResetEvent> handles = new List<ManualResetEvent>();
foreach (RegistryHive hive in Enum.GetValues(typeof(RegistryHive)))
{
foreach (RegistryView view in Enum.GetValues(typeof(RegistryView)).Cast<RegistryView>().ToList().Where(x => x != RegistryView.Default))
{
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
handles.Add(manualResetEvent);
new Thread(() =>
{
Console.WriteLine("Walking hive {0} in registry view {1}.", hive.ToString(), view.ToString());
WalkKey(connection, view, RegistryKey.OpenBaseKey(hive, view));
Console.WriteLine("Finished walking hive {0} in registry view {1}.", hive.ToString(), view.ToString());
manualResetEvent.Set();
Console.WriteLine("Finished setting event for hive {0} in registry view {1}.", hive.ToString(), view.ToString());
}).Start();
}
}
ManualResetEvent.WaitAll(handles.ToArray());
}
private static void WalkKey(SQLiteConnection connection, RegistryView view, RegistryKey key)
{
RegistryPath path = new RegistryPath(view, key.Name);
AddEntry(connection, path);
string[] valueNames = null;
try
{
valueNames = key.GetValueNames();
}
catch { }
if (valueNames != null)
{
foreach (string valueName in valueNames)
{
RegistryValueKind valueKind = RegistryValueKind.Unknown;
try
{
valueKind = key.GetValueKind(valueName);
}
catch { }
object value = key.GetValue(valueName);
RegistryPath pathForValue = new RegistryPath(view, key.Name, valueKind, valueName, value);
AddEntry(connection, pathForValue);
}
}
string[] subKeyNames = null;
try
{
subKeyNames = key.GetSubKeyNames();
}
catch { }
if (subKeyNames != null)
{
foreach (string subKeyName in subKeyNames)
{
try
{
WalkKey(connection, view, key.OpenSubKey(subKeyName));
}
catch { }
}
}
}
class RegistryPath
{
public RegistryView View;
public string Path;
public bool IsKey;
public RegistryValueKind ValueKind;
public string ValueName;
public object Value;
public int HashValue;
public RegistryPath(RegistryView view, string path)
{
View = view;
Path = path;
IsKey = true;
HashValue = (view.GetHashCode() ^ path.GetHashCode()).GetHashCode();
}
public RegistryPath(RegistryView view, string path, RegistryValueKind valueKind, string valueName, object value)
{
View = view;
Path = path;
IsKey = false;
ValueKind = valueKind;
ValueName = valueName;
Value = value;
if (value != null)
{
HashValue = (view.GetHashCode() ^ path.GetHashCode() ^ valueKind.GetHashCode() ^ valueName.GetHashCode() ^ value.GetHashCode()).GetHashCode();
}
else
{
HashValue = (view.GetHashCode() ^ path.GetHashCode() ^ valueKind.GetHashCode() ^ valueName.GetHashCode()).GetHashCode();
}
}
}
}
}
由于应用程序是线程化的,因此 AddEntry 围绕事务使用并发。最初,我没有使用插入计数器,但后来我很快意识到,由于我的应用程序是为 x86 构建的并使用 .NET Framework 4.5.1,只要应用程序有将近 2GB 的 RAM,它就会完全卡住,导致我相信这是由于 x86 系统上的 SQLite 中的另一个问题,例如 x86 上 .NET 中集合的 2GB RAM 限制。我使用了一个插入计数器来尝试经常提交事务,以免遇到大型事务队列。现在,即使我这样做了,我仍然会遇到此 AccessViolationException。我不确定是什么原因造成的。有人有任何线索吗?完整代码在这里,您可以将其复制并粘贴到控制台应用程序中并亲自查看。我只是希望你有一个相当强大的注册表。非常感谢帮助;提前致谢!
最佳答案
CL.这值得赞扬;他提到SQLite can be safely used by multiple threads provided that no single database connection is used simultaneously in two or more threads .
这种方法解决了问题:
using Microsoft.Win32;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace RegistryMonitor
{
class Program
{
static void Main(string[] args)
{
GenerateRegistrySnapshot("SnapshotOne.sqlite");
Console.ReadLine();
}
static void GenerateRegistrySnapshot(string filename)
{
File.Delete(filename);
SQLiteConnection.CreateFile(filename);
bool finished = false;
ConcurrentQueue<RegistryPath> queue = new ConcurrentQueue<RegistryPath>();
Thread worker = new Thread(() =>
{
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;"))
{
connection.Open();
CreateTable(connection);
SQLiteTransaction transaction = connection.BeginTransaction();
RegistryPath path;
while (!finished)
{
while (queue.TryDequeue(out path))
{
AddEntry(connection, path);
}
Thread.Sleep(100);
}
transaction.Commit();
transaction.Dispose();
connection.Close();
}
});
worker.Start();
Stopwatch watch = new Stopwatch();
Console.WriteLine("Started walking the registry into file {0}.", filename);
watch.Start();
WalkTheRegistryAndPopulateTheSnapshot(queue);
finished = true;
worker.Join();
watch.Stop();
Console.WriteLine("Finished walking the registry in {0} seconds.", watch.Elapsed.TotalSeconds);
}
static void CreateTable(SQLiteConnection connection)
{
SQLiteCommand command = new SQLiteCommand("CREATE TABLE Snapshot (ID INTEGER PRIMARY KEY AUTOINCREMENT, RegistryView INTEGER NULL, Path TEXT NULL, IsKey BOOLEAN NULL, RegistryValueKind INTEGER NULL, ValueName TEXT NULL, Value BLOB NULL, HashValue INTEGER NULL)", connection);
command.ExecuteNonQuery();
}
static void AddEntry(SQLiteConnection connection, RegistryPath path)
{
SQLiteCommand command = new SQLiteCommand("INSERT INTO Snapshot (RegistryView, Path, IsKey, RegistryValueKind, ValueName, Value, HashValue) VALUES (@RegistryView, @Path, @IsKey, @RegistryValueKind, @ValueName, @Value, @HashValue)", connection);
command.Parameters.Add("@RegistryView", DbType.Int32).Value = path.View;
command.Parameters.Add("@Path", DbType.String).Value = path.Path;
command.Parameters.Add("@IsKey", DbType.Boolean).Value = path.IsKey;
command.Parameters.Add("@RegistryValueKind", DbType.Int32).Value = path.ValueKind;
command.Parameters.Add("@ValueName", DbType.String).Value = path.ValueName;
command.Parameters.Add("@Value", DbType.Object).Value = path.Value;
command.Parameters.Add("@HashValue", DbType.Int32).Value = path.HashValue;
command.ExecuteNonQuery();
}
private static void WalkTheRegistryAndPopulateTheSnapshot(ConcurrentQueue<RegistryPath> queue)
{
List<ManualResetEvent> handles = new List<ManualResetEvent>();
foreach (RegistryHive hive in Enum.GetValues(typeof(RegistryHive)))
{
foreach (RegistryView view in Enum.GetValues(typeof(RegistryView)).Cast<RegistryView>().ToList().Where(x => x != RegistryView.Default))
{
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
handles.Add(manualResetEvent);
new Thread(() =>
{
WalkKey(queue, view, RegistryKey.OpenBaseKey(hive, view));
manualResetEvent.Set();
}).Start();
}
}
ManualResetEvent.WaitAll(handles.ToArray());
}
private static void WalkKey(ConcurrentQueue<RegistryPath> queue, RegistryView view, RegistryKey key)
{
RegistryPath path = new RegistryPath(view, key.Name);
queue.Enqueue(path);
string[] valueNames = null;
try
{
valueNames = key.GetValueNames();
}
catch { }
if (valueNames != null)
{
foreach (string valueName in valueNames)
{
RegistryValueKind valueKind = RegistryValueKind.Unknown;
try
{
valueKind = key.GetValueKind(valueName);
}
catch { }
object value = key.GetValue(valueName);
RegistryPath pathForValue = new RegistryPath(view, key.Name, valueKind, valueName, value);
queue.Enqueue(pathForValue);
}
}
string[] subKeyNames = null;
try
{
subKeyNames = key.GetSubKeyNames();
}
catch { }
if (subKeyNames != null)
{
foreach (string subKeyName in subKeyNames)
{
try
{
WalkKey(queue, view, key.OpenSubKey(subKeyName));
}
catch { }
}
}
}
class RegistryPath
{
public RegistryView View;
public string Path;
public bool IsKey;
public RegistryValueKind ValueKind;
public string ValueName;
public object Value;
public int HashValue;
public RegistryPath(RegistryView view, string path)
{
View = view;
Path = path;
IsKey = true;
HashValue = (view.GetHashCode() ^ path.GetHashCode()).GetHashCode();
}
public RegistryPath(RegistryView view, string path, RegistryValueKind valueKind, string valueName, object value)
{
View = view;
Path = path;
IsKey = false;
ValueKind = valueKind;
ValueName = valueName;
Value = value;
if (value != null)
{
HashValue = (view.GetHashCode() ^ path.GetHashCode() ^ valueKind.GetHashCode() ^ valueName.GetHashCode() ^ value.GetHashCode()).GetHashCode();
}
else
{
HashValue = (view.GetHashCode() ^ path.GetHashCode() ^ valueKind.GetHashCode() ^ valueName.GetHashCode()).GetHashCode();
}
}
}
}
}
编辑:甚至可能是这样的(内存使用量非常小)...
using Microsoft.Win32;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace RegistryMonitor
{
class Program
{
static void Main(string[] args)
{
GenerateRegistrySnapshot("Snapshot.sqlite");
Console.ReadLine();
}
static object writeLock = new object();
static AutoResetEvent writeReady = new AutoResetEvent(false);
static AutoResetEvent writeCompleted = new AutoResetEvent(false);
static RegistryPath pathToWrite;
static void GenerateRegistrySnapshot(string filename)
{
File.Delete(filename);
SQLiteConnection.CreateFile(filename);
bool finished = false;
Thread worker = new Thread(() =>
{
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;"))
{
connection.Open();
CreateTable(connection);
SQLiteTransaction transaction = connection.BeginTransaction();
while (!finished)
{
writeReady.WaitOne();
if (finished)
{
break;
}
AddEntry(connection, pathToWrite);
writeCompleted.Set();
}
transaction.Commit();
transaction.Dispose();
connection.Close();
}
});
worker.Start();
Stopwatch watch = new Stopwatch();
Console.WriteLine("Started walking the registry into file {0}.", filename);
watch.Start();
WalkTheRegistryAndPopulateTheSnapshot();
finished = true;
writeReady.Set();
worker.Join();
watch.Stop();
Console.WriteLine("Finished walking the registry in {0} seconds.", watch.Elapsed.TotalSeconds);
}
static void CreateTable(SQLiteConnection connection)
{
SQLiteCommand command = new SQLiteCommand("CREATE TABLE Snapshot (ID INTEGER PRIMARY KEY AUTOINCREMENT, RegistryView INTEGER NULL, Path TEXT NULL, IsKey BOOLEAN NULL, RegistryValueKind INTEGER NULL, ValueName TEXT NULL, Value BLOB NULL, HashValue INTEGER NULL)", connection);
command.ExecuteNonQuery();
}
static void AddEntry(SQLiteConnection connection, RegistryPath path)
{
SQLiteCommand command = new SQLiteCommand("INSERT INTO Snapshot (RegistryView, Path, IsKey, RegistryValueKind, ValueName, Value, HashValue) VALUES (@RegistryView, @Path, @IsKey, @RegistryValueKind, @ValueName, @Value, @HashValue)", connection);
command.Parameters.Add("@RegistryView", DbType.Int32).Value = path.View;
command.Parameters.Add("@Path", DbType.String).Value = path.Path;
command.Parameters.Add("@IsKey", DbType.Boolean).Value = path.IsKey;
command.Parameters.Add("@RegistryValueKind", DbType.Int32).Value = path.ValueKind;
command.Parameters.Add("@ValueName", DbType.String).Value = path.ValueName;
command.Parameters.Add("@Value", DbType.Object).Value = path.Value;
command.Parameters.Add("@HashValue", DbType.Int32).Value = path.HashValue;
command.ExecuteNonQuery();
}
private static void WalkTheRegistryAndPopulateTheSnapshot()
{
List<ManualResetEvent> handles = new List<ManualResetEvent>();
foreach (RegistryHive hive in Enum.GetValues(typeof(RegistryHive)))
{
foreach (RegistryView view in Enum.GetValues(typeof(RegistryView)).Cast<RegistryView>().ToList().Where(x => x != RegistryView.Default))
{
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
handles.Add(manualResetEvent);
new Thread(() =>
{
WalkKey(view, RegistryKey.OpenBaseKey(hive, view));
manualResetEvent.Set();
}).Start();
}
}
ManualResetEvent.WaitAll(handles.ToArray());
}
private static void WalkKey(RegistryView view, RegistryKey key)
{
RegistryPath path = new RegistryPath(view, key.Name);
Write(path);
string[] valueNames = null;
try
{
valueNames = key.GetValueNames();
}
catch { }
if (valueNames != null)
{
foreach (string valueName in valueNames)
{
RegistryValueKind valueKind = RegistryValueKind.Unknown;
try
{
valueKind = key.GetValueKind(valueName);
}
catch { }
object value = key.GetValue(valueName);
RegistryPath pathForValue = new RegistryPath(view, key.Name, valueKind, valueName, value);
Write(pathForValue);
}
}
string[] subKeyNames = null;
try
{
subKeyNames = key.GetSubKeyNames();
}
catch { }
if (subKeyNames != null)
{
foreach (string subKeyName in subKeyNames)
{
try
{
WalkKey(view, key.OpenSubKey(subKeyName));
}
catch { }
}
}
}
private static void Write(RegistryPath path)
{
lock (writeLock)
{
pathToWrite = path;
writeReady.Set();
writeCompleted.WaitOne();
}
}
class RegistryPath
{
public RegistryView View;
public string Path;
public bool IsKey;
public RegistryValueKind ValueKind;
public string ValueName;
public object Value;
public int HashValue;
public RegistryPath(RegistryView view, string path)
{
View = view;
Path = path;
IsKey = true;
HashValue = (view.GetHashCode() ^ path.GetHashCode()).GetHashCode();
}
public RegistryPath(RegistryView view, string path, RegistryValueKind valueKind, string valueName, object value)
{
View = view;
Path = path;
IsKey = false;
ValueKind = valueKind;
ValueName = valueName;
Value = value;
if (value != null)
{
HashValue = (view.GetHashCode() ^ path.GetHashCode() ^ valueKind.GetHashCode() ^ valueName.GetHashCode() ^ value.GetHashCode()).GetHashCode();
}
else
{
HashValue = (view.GetHashCode() ^ path.GetHashCode() ^ valueKind.GetHashCode() ^ valueName.GetHashCode()).GetHashCode();
}
}
}
}
}
关于c# - System.AccessViolationException 与 SQLite,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26951201/
我有一个正在运行的服务,它连接到几个客户端。它已经启动并运行了数周,并且该函数每分钟被调用多次,我在不同的函数中遇到了一些问题,但是这个异常让它一直崩溃。我以前从未见过这个问题。谁能让这发生? 堆栈:
我们正在使用 Kinect 流式传输用户的可自定义视频,您可以在不停止流的情况下选择流类型(颜色、深度,都可以选择显示跟踪的骨架)。 如果我们更改流类型,我们的程序运行良好,但在启用框架的几帧(并且仅
我正在尝试使用 Steve Sanderson's blog post为了在我的 ASP MVC 3 View 中编辑可变长度列表。该项目构建良好,但是每当呈现局部 View 时,程序就会在 usin
我在 C# 中使用了很长时间,但我从未遇到过这种错误。首先,您是否看到关于这个单个代码块的任何错误(可能是错误的)(当然除了它的逻辑,我知道它总是返回 0)? public static int Ge
我在 .net 应用程序中使用 COM 对象 (MODI)。我调用的方法抛出 System.AccessViolationException,它被 Visual Studio 拦截。奇怪的是,我将我的
我正在编写这个库,它通过媒体基础框架在 C++/CLI 中实现一些基本的音频播放器功能,这些功能将由托管代码使用。我可以播放音频、停止、暂停等。对于不熟悉媒体基础的任何人,媒体 session 都会发
我们遇到的问题是有时 AccessViolationException会出现一个简单的组框,它带有白色背景,上面有一个红十字。我们无法可靠地重现此错误,它只是不时发生。 我们没有做任何特别的事情,我们
我正在处理一个目录项目,当程序没有被使用或空闲 3 分钟时,一个充当 的表单待机屏幕播放视频将显示(我使用 AxWindowsMediaPlayer )。通过单击表单中的任意位置,待机屏幕将关闭并返回
我有一个在 VS2015 和 .Net 4.5.2 中运行的大型 vb.net x86 项目 当它在没有优化的情况下编译并在调试中运行时,它可以正常工作。但是,如果我在 Release模式下编译并运行
我们使用自动崩溃报告工具(即 http://crashrpt.sourceforge.net)来生成崩溃报告。 因此,如果一段非托管代码通过访问 NULL 失败例如,应用程序崩溃,崩溃报告工具激活,我
我有一个Windows服务,它以未处理的方式崩溃,但异常System.AccessViolationException。尝试加载用户个人资料时(在模拟过程中),我确实发生过1000种情况之一。我对找到
我正在使用 Excel 2010 和 VSTO 4 在 .NET 4.0 (C#) 中开发 Excel 加载项。在我的 Excel 访问器类中,我有一个属性“CurrentWorkbook”,它返回
大约一周前,每当我在某个文本框中键入内容时,我正在开发的一个程序就会开始崩溃,并出现 AccessViolationException。我已将其简化为这个测试用例,但我没有主意: Imports Sy
当我从 Visual C++ 以 Release模式运行我的应用程序时,出现以下异常。 Unhandled Exception: System.AccessViolationException: At
我在我的程序中使用了一个外部 C 库,用 C++/CLI 和 .NET 框架 4 编码。有时库崩溃,我收到消息: Unhandled Exception: System.AccessViolation
我已经为 SAPI5 Eliska22k 安装了捷克语音。它在 Windows 7 上工作正常。现在我有 Windows 8,在调用 Speak 方法时它给了我 Attempted to read o
我正在使用 wkHTMLtoXSharp 包装器在 Windows 2008 R2 上调用 wkHTMLtoPDF 库。除了一个异常(exception),一切都很好。我正在从 C# Windows
我正在尝试使用来自 C# 的非托管 API,并用头撞墙。 (就 PInvoke 而言,我是一个初学者。) 头文件的相关部分如下所示: #define CTAPICALL __stdcall
我正在尝试与实现多个函数的 Dll 进行交互,其中一个采用以空字符结尾的字符串和一个 int,并返回以空字符结尾的字符串。我试图与这样的方法交互: [DllImport(dll_loc)] [retu
我有一个 asp.net (3.5) 网络应用程序。在一个页面中,我使用了一个非托管 C 库(一个模拟器),它根据一些输入生成一组结果。 当我在 web.config( Release模式)中设置 d
我是一名优秀的程序员,十分优秀!