Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Other SQL Server 2008 Topics
 CLR TVF - Limited References List!

Author  Topic 

SMerrill
Posting Yak Master

206 Posts

Posted - 2010-05-10 : 19:19:31
I need to write a Table-valued function that reads something from WMI, as a proof-of-concept that it can be done.

I tried to do so in SQL CLR, but the list of References one could choose from was quite limited.

MSDN is replete with references to the new System.Management API, and that is one of the references that I cannot place into a CLR.

Is there any way to get around the limited list of SQL-authorized .NET DLL's?

~ Shaun Merrill
Seattle area

jezemine
Master Smack Fu Yak Hacker

2886 Posts

Posted - 2010-05-11 : 01:02:52
this is possible, I think, but difficult and not recommended. You'd have to import System.Management.dll and all its dependencies to SQL Server first before importing your own assembly. Also would have to import as UNSAFE assemblies.

Probably it would be easier to forget about doing this via a CLR proc just call WMI via xp_cmdshell instead.




elsasoft.org
Go to Top of Page

SMerrill
Posting Yak Master

206 Posts

Posted - 2010-05-13 : 13:22:05
The requirement is to write a SMS report based upon WMI data, so I cannot just skip this like a rock.

So far, I've found that in C# I'm using this to talk to WMI . . .
(Activator.CreateInstance(Type.GetTypeFromProgID("System.Management"))

and in VB.NET one could use CreateObject() for late-bound calls.

This technique is among the limited set of stuff we can use, but now I'm running into security issues, where it is recommending I use the security policy to bless certain DLLs. I've never done that before.

It occurred to me that I could write two processes--one with the DLL's I need that takes WMI out of the equation, and the other being my TVF code. Then I figure I could launch my WMI reader as a second thread, and have it throw an event when it is finished.

It shouldn't be so hard!
Stick with me here. . . I'm kinda behind the ol' .

~ Shaun Merrill
Seattle area
Go to Top of Page

SMerrill
Posting Yak Master

206 Posts

Posted - 2010-05-13 : 15:02:40
jesemine: I noticed that the only dependencies of System.Management.dll are mscorlib.dll and system.dll, which makes it simpler than expected. So what is the process for importing System.Management.dll into SQL as UNSAFE, and what are the gotcha's on that?

~ Shaun Merrill
Seattle area
Go to Top of Page

jezemine
Master Smack Fu Yak Hacker

2886 Posts

Posted - 2010-05-13 : 22:42:10
trust me, this is not a good way to go. Just write your own cmd line app to do what you want, and call it from xp_cmdshell.


elsasoft.org
Go to Top of Page

SMerrill
Posting Yak Master

206 Posts

Posted - 2010-05-17 : 13:40:30
Here is what I ended up with. There are several good techniques exercised here, which could make a start for a great article on WMI.

The purpose here is to read WMI into a table, and the cool techniques are:
* Run a command-line application catching error messages and output.
* Read a raw XML file into an XML variable and parse something out of it.
* Use TRY/CATCH with proper error throwing.


-- Create a table to receive WMI information
BEGIN TRAN
IF OBJECT_ID(N'[DBO].[WMIDATATEST]') IS NOT NULL
DROP TABLE DBO.WMIDATATEST;

CREATE TABLE Dbo.WmiDataTest (
ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
Class VARCHAR(200) NOT NULL,
Property VARCHAR(200) NOT NULL,
VarType VARCHAR(200) NOT NULL,
Value VARCHAR(200) NULL
);
GRANT SELECT ON dbo.WmiDataTest TO webreport_approle;
COMMIT TRAN
go
SET NOCOUNT ON;

DECLARE @CMD VARCHAR(8000);
DECLARE @X XML;
DECLARE @IDOC INT;
DECLARE @Class VARCHAR(20);
DECLARE @Ret INT;
DECLARE @RetTable TABLE ([Output] nvarchar(255) );
BEGIN TRY
SET @Class = 'Printer'

--generate the XML using WMIC.EXE and write it into a file
-- after I gave write permission on the output folder to SQL, this worked.
set @CMD = 'WMIC ' + @Class + ' get /translate:basicxml /format:rawxml.xsl '
+ '> c:\users\Shaun\documents\outputs\win32_printer_instances.xml'
INSERT INTO @RetTable EXECUTE @Ret = XP_CMDSHELL @CMD;
IF (@RET = 0)
BEGIN
--READ THE XML INTO A VARIABLE
SELECT @X = CAST(BULKCOLUMN AS XML) FROM OPENROWSET (
BULK 'c:\users\Shaun\documents\outputs\win32_printer_instances.xml' ,SINGLE_BLOB
) AS XMLDATA;

--PARSE THE DESIRED XML VALUES IN THE VARIABLE AND INSERT THEM INTO THE TABLE
EXEC sp_xml_PrepareDocument @idoc OUTPUT, @X;

INSERT INTO dbo.WmiDataTest (Class, property, vartype, value)
SELECT Class, Property, VarType, CASE LTRIM(RTRIM(Value))
WHEN 'NULL' THEN NULL
ELSE Value
END
FROM OPENXML (@idoc, '//PROPERTY')
WITH (
Class VARCHAR(200) './@CLASSORIGIN'
, Property VARCHAR(200) './@NAME'
, VarType VARCHAR(200) './@TYPE'
, Value VARCHAR(200) './VALUE'
) ;
EXEC sp_xml_RemoveDocument @idoc;
END
ELSE
BEGIN
DECLARE @Message VARCHAR(255);
SELECT TOP 1 @Message = [Output] FROM @RetTable;
RAISERROR ( 'WMIC.EXE failed with this message: %s', 16, 1, @Message );
-- Wmic.exe can only be used by the local system administrators
-- regardless of WMI namespace permissions on the local machine.
END;
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR ( @ErrorMessage, @ErrorSeverity, @ErrorState );
END CATCH;

SELECT * FROM dbo.WmiDataTest;


~ Shaun Merrill
Seattle area
Go to Top of Page
   

- Advertisement -