Getting mount point when a USB device is inserted Mac OS X and linux - macos

I am trying to develop a program in Mac OS and Linux which lists the files and folders in USB drive. I need to get the some events when USB device is connected and removed. I know that in Mac OS X I can use IOKit. But I do n't know how to get the mount point where the device is mounted. Can I get it using IOkit? Is there any cross platform solution for Linux and Mac?

No, there isn't. Under Linux you may use HAL or DeviceKit-disks D-Bus interfaces. Note those are optional components and may be absent. HAL is older and DeviceKit-disks is newer implementations, with DK-d replacing HAL.

The approach I used for getting the available mount-points (with Java) pipes the output of the "system_profiler SPUSBDataType -xml" command to dd-plist processor. It subsequently recurses over the USB hierarchy, matching those having a "volumes" key. For each item in this array, retrieve the "mount_point" key to retrieve the location where it is mounted. See the code sample below:
/*
Copyright © 2014 Edwin de Jong. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY [LICENSOR] "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package nl.topicuszorg.laos.util.osx;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import nl.topicuszorg.laos.model.response.MountState;
import nl.topicuszorg.laos.model.response.MountedDevice;
import org.xml.sax.SAXException;
import com.dd.plist.NSArray;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.NSString;
import com.dd.plist.PropertyListFormatException;
import com.dd.plist.PropertyListParser;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
public class USBHelpers
{
private static final String SYSTEM_PROFILER_COMMAND = "/usr/sbin/system_profiler";
private static final String SPUSB_DATA_TYPE = "SPUSBDataType";
private interface SpUSBDataTypeIdentifiers
{
String ITEMS = "_items";
String VOLUMES = "volumes";
String VENDOR_ID = "vendor_id";
String MOUNT_POINT = "mount_point";
String NAME = "_name";
}
public static List<MountedDevice> findMountedDevicesOsX() throws IOException, PropertyListFormatException,
ParseException, ParserConfigurationException, SAXException
{
final Process process = new ProcessBuilder(SYSTEM_PROFILER_COMMAND, SPUSB_DATA_TYPE, "-xml")
.start();
return findMountedDevicesInConfiguration(process.getInputStream());
}
private static List<MountedDevice> findMountedDevicesInConfiguration(final InputStream processInputStream)
throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException
{
// Root is an array, the USB devices are hierarchical in _items (and eg. _items(0)._items)
final NSArray array = (NSArray) (PropertyListParser.parse(processInputStream));
final NSDictionary dict = (NSDictionary) array.objectAtIndex(0);
final NSArray itemsArray = (NSArray) dict.get(SpUSBDataTypeIdentifiers.ITEMS);
return recurseUSBDevices(itemsArray);
}
public static List<MountedDevice> recurseUSBDevices(NSArray items)
{
final Builder<MountedDevice> builder = ImmutableList.builder();
for (NSObject item : items.getArray())
{
builder.addAll(recurseUSBDevice((NSDictionary) item));
}
return builder.build();
}
private static List<MountedDevice> recurseUSBDevice(final NSDictionary dict)
{
final Builder<MountedDevice> builder = ImmutableList.builder();
for (final Map.Entry<String, NSObject> entry : dict.entrySet())
{
if (entry.getKey().equals(SpUSBDataTypeIdentifiers.ITEMS))
{
// The USB device is a hub
builder.addAll(recurseUSBDevices((NSArray) entry.getValue()));
}
if (entry.getKey().equals(SpUSBDataTypeIdentifiers.VOLUMES))
{
// This is a mountable device. We need to get the volumes, and for each volume, return it.
List<MountedDevice> mountedDeviceOpt = parseVolumes((NSArray) (entry.getValue()));
for (MountedDevice mountedDevice : mountedDeviceOpt)
{
mountedDevice.setVendorId(((NSString) dict.get(SpUSBDataTypeIdentifiers.VENDOR_ID)).toString());
builder.add(mountedDevice);
}
}
}
return builder.build();
}
private static List<MountedDevice> parseVolumes(final NSArray nsArray)
{
final Builder<MountedDevice> builder = ImmutableList.builder();
for (final NSObject item : nsArray.getArray())
{
builder.add(parseVolume((NSDictionary) item));
}
return builder.build();
}
private static MountedDevice parseVolume(final NSDictionary item)
{
final String mountPoint = ((NSString) item.get(SpUSBDataTypeIdentifiers.MOUNT_POINT)).toString();
final String name = ((NSString) item.get(SpUSBDataTypeIdentifiers.NAME)).toString();
return new MountedDevice(mountPoint, name, null, null, MountState.MOUNTED);
}
}

Related

windows 10 determine if "maintain aspect ratio" is set on a PCs GPU

I am trying to programically determine if a video card is set to "maintain aspect ratio". I've tracked down this registry key in windows.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\\00\00
scaling =
4 = maintain aspect ratio 3 = scale full screen 2 = center image
This would be great, but it appears that "maintain display scaling" will retain whatever that key was set to before.
Does anyone have another location or another method to confirm, that a video card is set to maintain aspect ratio? (not using a cards GUI)
I should clarify this isn't about DPI settings, this is about aspect ratio of the video being displayed.
Posting this as an answer (even though it's not) since I need to space to show what I've done so far--in case it helps anyone towards the answer. I'm currently looking through other Windows API libs to try and find the answer.
#MinerBob, I saw that guy's code yesterday too but couldn't get it to work so I changed a few things and am now reporting the data as correctly as I can but looking over the struct, it doesn't appear to contain the information you're after but here's how you can generate the output to review it yourself:
Add-Type "
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public ScreenOrientation dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}
public static class user32
{
[DllImport(`"user32.dll`")]
public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
public const int ENUM_CURRENT_SETTINGS = -1;
public const int ENUM_REGISTRY_SETTINGS = -2;
public static void GetDisplaySettings()
{
DEVMODE vDevMode = new DEVMODE();
if (EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref vDevMode))
{
Console.WriteLine(#`"
dmDeviceName = {0}
dmSpecVersion = {1}
dmDriverVersion = {2}
dmSize = {3}
dmDriverExtra = {4}
dmFields = {5}
dmPositionX = {6}
dmPositionY = {7}
dmDisplayOrientation = {8}
dmDisplayFixedOutput = {9}
dmColor = {10}
dmDuplex = {11}
dmYResolution = {12}
dmTTOption = {13}
dmCollate = {14}
dmFormName = {15}
dmLogPixels = {16}
dmBitsPerPel = {17}
dmPelsWidth = {18}
dmPelsHeight = {19}
dmDisplayFlags = {20}
dmDisplayFrequency = {21}
dmICMMethod = {22}
dmICMIntent = {23}
dmMediaType = {24}
dmDitherType = {25}
dmReserved1 = {26}
dmReserved2 = {27}
dmPanningWidth = {28}
dmPanningHeight = {29}
`",
vDevMode.dmDeviceName,
vDevMode.dmSpecVersion,
vDevMode.dmDriverVersion,
vDevMode.dmSize,
vDevMode.dmDriverExtra,
vDevMode.dmFields,
vDevMode.dmPositionX,
vDevMode.dmPositionY,
vDevMode.dmDisplayOrientation,
vDevMode.dmDisplayFixedOutput,
vDevMode.dmColor,
vDevMode.dmDuplex,
vDevMode.dmYResolution,
vDevMode.dmTTOption,
vDevMode.dmCollate,
vDevMode.dmFormName,
vDevMode.dmLogPixels,
vDevMode.dmBitsPerPel,
vDevMode.dmPelsWidth,
vDevMode.dmPelsHeight,
vDevMode.dmDisplayFlags,
vDevMode.dmDisplayFrequency,
vDevMode.dmICMMethod,
vDevMode.dmICMIntent,
vDevMode.dmMediaType,
vDevMode.dmDitherType,
vDevMode.dmReserved1,
vDevMode.dmReserved2,
vDevMode.dmPanningWidth,
vDevMode.dmPanningHeight
);
}
}
}
" -ReferencedAssemblies System.Windows.Forms
[user32]::GetDisplaySettings()
UPDATE 1:
According to the MSDN documentation for EnumDisplaySettings:
The EnumDisplaySettings function sets values for the following five
DEVMODE members:
dmBitsPerPel
dmPelsWidth
dmPelsHeight
dmDisplayFlags
dmDisplayFrequency
what I was originally focusing on 'dmScale' appears to be specific to Printers--as in, only Printer functions that populate the DEVMODE struct will fill that field.
Update 2:
It appears everything under GraphicsDrivers key, well, is updated by the graphics driver that's loaded for that monitor. Very Intuitive. Every article I could find talks about either changing the value in the vendor-specific UI that interacts with its driver OR using the appropriate monitor key under Graphics Drivers to interact with this feature.
There must be some Windows Graphics Driver documentation that talks about each driver updating/honoring these values. Looking for that now to confirm.
Update 3:
Updated source to include the DEVMODE structure signature from pinvoke.net. Also, I believe I found the smoking gun in Windows driver documentation:
Scaling depends on the source and target modes that are used for a
path. In addition, the caller can call SetDisplayConfig without
specifying the target mode information (that is, setting the
modeInfoArray parameter is optional and can be set to NULL).
Therefore, the caller cannot typically predict if SetDisplayConfig
must perform any scaling. Furthermore, no API exists to get the full
list of scaling types that the graphics adapter supports. The
EnumDisplaySettings Win32 function (described in the Windows SDK
documentation) returns DMDFO_DEFAULT in the dmDisplayFixedOutput
member of the DEVMODE structure that the lpDevMode parameter points to
when the caller requests the new Windows 7 scaling types.
The scaling that a caller passes to SetDisplayConfig is a scaling
intent rather than an explicit request to perform a scaling operation.
If scaling is required (for example, source and target resolutions
differ), SetDisplayConfig uses the scaling that the caller supplies.
If the supplied scaling is not supported, SetDisplayConfig uses the
graphics adapter's default scaling. When the source and target
resolutions that the caller passes to SetDisplayConfig are the same,
SetDisplayConfig always sets identify scaling.
...my bolded emphasis. DMDFO_DEFAULT, according to the header file, is 0.
Sources:
https://learn.microsoft.com/en-us/windows-hardware/drivers/display/scaling-the-desktop-image
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodea

How does the POI Event API read data from Excel and why does it use less RAM?

I am currently writing my bachelor thesis and I am using the POI Event API from Apache. In short, my work is about a more efficient way to read data from Excel.
I get asked by developers again and again how exactly this is meant with Event API. Unfortunately I don't find anything on the Apache page about the basic principle.
Following code, how I use the POI Event API (This is from the Apache example for XSSF and SAX):
import java.io.InputStream;
import java.util.Iterator;
import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
public class ExampleEventUserModel {
public void processOneSheet(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
// To look up the Sheet Name / Sheet Order / rID,
// you need to process the core Workbook stream.
// Normally it's of the form rId# or rSheet#
InputStream sheet2 = r.getSheet("rId2");
InputSource sheetSource = new InputSource(sheet2);
parser.parse(sheetSource);
sheet2.close();
}
public void processAllSheets(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
Iterator<InputStream> sheets = r.getSheetsData();
while(sheets.hasNext()) {
System.out.println("Processing new sheet:\n");
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
System.out.println("");
}
}
public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException, ParserConfigurationException {
XMLReader parser = SAXHelper.newXMLReader();
ContentHandler handler = new SheetHandler(sst);
parser.setContentHandler(handler);
return parser;
}
/**
* See org.xml.sax.helpers.DefaultHandler javadocs
*/
private static class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private SheetHandler(SharedStringsTable sst) {
this.sst = sst;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => cell
if(name.equals("c")) {
// Print the cell reference
System.out.print(attributes.getValue("r") + " - ");
// Figure out if the value is an index in the SST
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// Clear contents cache
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = sst.getItemAt(idx).getString();
nextIsString = false;
}
// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
System.out.println(lastContents);
}
}
public void characters(char[] ch, int start, int length) {
lastContents += new String(ch, start, length);
}
}
public static void main(String[] args) throws Exception {
ExampleEventUserModel example = new ExampleEventUserModel();
example.processOneSheet(args[0]);
example.processAllSheets(args[0]);
}
}
Can someone please explain to me how the Event API works? Is it the same as the event-based architecture or is it something else?
A *.xlsx file, which is Excel stored in Office Open XML and is what apache poi handles as XSSF, is a ZIP archive containing the data in XML files within a directory structure. So we can unzip the *.xlsx file and get the data directly from the XML files then.
There is /xl/sharedStrings.xml having all the string cell values in it. And there is /xl/workbook.xml describing the workbook structure. And there are /xl/worksheets/sheet1.xml, /xl/worksheets/sheet2.xml, ... which are storing the sheets' data. And there is /xl/styles.xml having the style settings for all cells in the sheets.
Per default while creating a XSSFWorkbook all those parts of the *.xlsx file will become object representations as XSSFWorkbook, XSSFSheet, XSSFRow, XSSFCell, ... and further objects of org.apache.poi.xssf.*.* in memory.
To get an impression of how memory consuming XSSFSheet, XSSFRow and XSSFCell are, a look into the sources will be good. Each of those objects contains multiple Lists and Maps as internally members and of course multiple methods too. Now imagine a sheet having hundreds of thousands of rows each containing up to hundreds of cells. Each of those rows and cells will be represented by a XSSFRow or a XSSFCell in memory. This cannot be an accusation to apache poi because those objects are necessary if working with those objects is needed. But if the need is really only getting the content out of the Excel sheet, then those objects are not all necessary. That's why the XSSF and SAX (Event API) approach.
So if the need is only reading data from sheets one could simply parsing the XML of all the /xl/worksheets/sheet[n].xml files without the need for creating memory consuming objects for each sheet and for each row and for each cell in those sheets.
Parsing XML in event based mode means that the code goes top down through the XML and has callback methods defined which get called if the code detects the start of an element, the end of an element or character content within an element. The appropriate callback methods then handle what to do on start, end or with character content of an element. So reading the XML file only means running top down through the file once, handle the events (start, end, character content of an element) and are able getting all needed content out of it. So memory consuming is reduced to storing the text data gotten from the XML.
XSSF and SAX (Event API) uses class SheetHandler which extends DefaultHandler for this.
But if we are already at this level where we get at the underlying XML data and process it, then we could go one more step back too. Native Java is able handling ZIP and parsing XML. So we would not even need additional libraries at all. See how read excel file having more than 100000 row in java? where I have shown this. My code uses Package javax.xml.stream which also provides using event based XMLEventReader but not using callbacks but linear code. Maybe this code is simpler to understand because it is all in one.
For detecting whether a number format is a date format, and so the formatted cell contains a date / time value, one single apache poi class org.apache.poi.ss.usermodel.DateUtil is used. This is done to simplify the code. Of course even this class we could have coded our self.

jcuda cuModuleLoad() cannot load file using the path of getClass().getResource().getPath()

I am trying to use cuModuleLoad() in JCuda to load a vectorAdd.ptx file from /src/main/resources. The code is as follows:
cuModuleLoad(module, getClass.getResource("vectorAdd.ptx").getPath())
But the cuModuleLoad() doesn't pick up this file. It only works when I pass in the absolute path of the ptx file. But I would like to have the ptx file shipped with compile jar files. Is there any way to accomplish this?
The cuModuleLoad function in JCuda is a direct mapping to the corresponding cuModuleLoad function in CUDA. It expects a file name as the second argument.
The problem is: cuModuleLoad can not load the PTX file, because the PTX file simply does not exist for CUDA! The PTX file is hidden inside the JAR file.
When you obtain a resource from a JAR file using someClass.getResource(), then it will point to the resource in the JAR file. When you do something like
System.out.println(getClass().getResource("vectorAdd.ptx").getPath());
and run this (as a JAR file), then you will see an output like this:
file:/U:/YourWorkspace/YourJarFile.jar!/vectorAdd.ptx
Note the .jar! part: This path is not a path to a real file, but only a path to a resource in the JAR.
In order to load the PTX file from a JAR, you have to read the PTX file from the JAR into a byte[] array on Java side, and then pass it to the cuModuleLoadData function of JCuda (which corresponds to the cuModuleLoadData function of CUDA).
Here is an example that loads the PTX data from a JAR file into a byte array, representing the zero-terminated string that can be passed to cuModuleLoadData:
import static jcuda.driver.JCudaDriver.cuCtxCreate;
import static jcuda.driver.JCudaDriver.cuDeviceGet;
import static jcuda.driver.JCudaDriver.cuInit;
import static jcuda.driver.JCudaDriver.cuModuleGetFunction;
import static jcuda.driver.JCudaDriver.cuModuleLoadData;
import static jcuda.runtime.JCuda.cudaDeviceReset;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import jcuda.driver.CUcontext;
import jcuda.driver.CUdevice;
import jcuda.driver.CUfunction;
import jcuda.driver.CUmodule;
import jcuda.driver.JCudaDriver;
public class JCudaPtxInJar
{
public static void main(String args[]) throws IOException
{
// Initialization
JCudaDriver.setExceptionsEnabled(true);
cuInit(0);
CUdevice device = new CUdevice();
cuDeviceGet(device, 0);
CUcontext context = new CUcontext();
cuCtxCreate(context, 0, device);
// Read the PTX data into a zero-terminated string byte array
byte ptxData[] = toZeroTerminatedStringByteArray(
JCudaPtxInJar.class.getResourceAsStream(
"JCudaVectorAddKernel.ptx"));
// Load the module data
CUmodule module = new CUmodule();
cuModuleLoadData(module, ptxData);
// Obtain a function pointer to the "add" function
// and print a simple test/debug message
CUfunction function = new CUfunction();
cuModuleGetFunction(function, module, "add");
System.out.println("Got function "+function);
cudaDeviceReset();
}
/**
* Read the contents of the given input stream, and return it
* as a byte array containing the ZERO-TERMINATED string data
* from the stream. The caller is responsible for closing the
* given stream.
*
* #param inputStream The input stream
* #return The ZERO-TERMINATED string byte array
* #throws IOException If an IO error occurs
*/
private static byte[] toZeroTerminatedStringByteArray(
InputStream inputStream) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buffer[] = new byte[8192];
while (true)
{
int read = inputStream.read(buffer);
if (read == -1)
{
break;
}
baos.write(buffer, 0, read);
}
baos.write(0);
return baos.toByteArray();
}
}
Compiling this and packing it into a JAR (together with the /resources/JCudaVectorAddKernel.ptx PTX file, of course) will allow you to start the program and obtain the example function from the PTX in the JAR.

With SerilogWeb.Owin discontinued, is there an "official" integration?

I came across the discontinuation notice of the SerilogWeb.Owin package, and in reading the GitHub issue there was discussion about "redirecting folks somewhere" given the ~5K+ downloads of the package.
But I haven't been able to figure out where I'm being redirected to!
So where should I be looking for a "Serilog-blessed" integration for using Serilog with an (OWIN) self-hosted Web API?
The package boils down to the following, which I derived from the issues in [the repo](https://github.com/serilog-web/owin/blob/master/src/SerilogWeb.Owin/Owin/LoggerFactory.cs
):
Adding a RequestId to allow traces to be correlated
using (Serilog.Context.LogContext.PushProperty("RequestId", Guid.NewGuid().ToString("N"))
Plug in a logger redirector:
app.SetLoggerFactory(new SerilogOwinFactory());
Copy in the impl (this works with WebApi 5.2.4, Katana 4.0, Serilog 2.6) and incorporates learnings from another question about efficiently forwarding events without the writing treating the message as a template, and ensuring the Exception is included a first class element of the message in order that it can be formatted and/or demystyfied corrrectly:
And the good news is that, when you reach ASP.NET Core, there will be a fully maintained package with a deeper integration waiting for you, with a one-liner hookin ;)
// From https://github.com/serilog-web/owin/blob/master/src/SerilogWeb.Owin/Owin/LoggerFactory.cs
// Copyright 2015 SerilogWeb, Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.Owin.Logging;
using Serilog;
using Serilog.Core;
using Serilog.Events;
using ILogger = Serilog.ILogger;
namespace SerilogWeb.Owin
{
/// <summary>
/// Implementation of Microsoft.Owin.Logger.ILoggerFactory.
/// </summary>
public class SerilogOwinFactory : ILoggerFactory
{
readonly Func<ILogger> _getLogger;
readonly Func<TraceEventType, LogEventLevel> _getLogEventLevel;
/// <summary>
/// Create a logger factory.
/// </summary>
/// <param name="logger">The logger; if not provided the global <see cref="Serilog.Log.Logger"/> will be used.</param>
/// <param name="getLogEventLevel"></param>
public SerilogOwinFactory(ILogger logger = null, Func<TraceEventType, LogEventLevel> getLogEventLevel = null)
{
_getLogger = logger == null ? (Func<ILogger>)(() => Log.Logger) : (() => logger);
_getLogEventLevel = getLogEventLevel ?? ToLogEventLevel;
}
/// <summary>
/// Creates a new ILogger instance of the given name.
/// </summary>
/// <param name="name">The logger context name.</param>
/// <returns>A logger instance.</returns>
public Microsoft.Owin.Logging.ILogger Create(string name)
{
return new Logger(_getLogger().ForContext(Constants.SourceContextPropertyName, name), _getLogEventLevel);
}
static LogEventLevel ToLogEventLevel(TraceEventType traceEventType)
{
switch (traceEventType)
{
case TraceEventType.Critical:
return LogEventLevel.Fatal;
case TraceEventType.Error:
return LogEventLevel.Error;
case TraceEventType.Warning:
return LogEventLevel.Warning;
case TraceEventType.Information:
return LogEventLevel.Information;
case TraceEventType.Verbose:
return LogEventLevel.Verbose;
case TraceEventType.Start:
return LogEventLevel.Debug;
case TraceEventType.Stop:
return LogEventLevel.Debug;
case TraceEventType.Suspend:
return LogEventLevel.Debug;
case TraceEventType.Resume:
return LogEventLevel.Debug;
case TraceEventType.Transfer:
return LogEventLevel.Debug;
default:
throw new ArgumentOutOfRangeException("traceEventType");
}
}
class Logger : Microsoft.Owin.Logging.ILogger
{
readonly ILogger _logger;
readonly Func<TraceEventType, LogEventLevel> _getLogEventLevel;
static readonly Exception _exceptionPlaceHolder = new Exception("(Exception enclosed)");
internal Logger(ILogger logger, Func<TraceEventType, LogEventLevel> getLogEventLevel)
{
_logger = logger;
_getLogEventLevel = getLogEventLevel;
}
public bool WriteCore(TraceEventType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
var level = _getLogEventLevel(eventType);
// According to docs http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin/Logging/ILogger.cs
// "To check IsEnabled call WriteCore with only TraceEventType and check the return value, no event will be written."
if (state == null)
return _logger.IsEnabled(level);
if (!_logger.IsEnabled(level))
return false;
var formattedMessage = formatter(state, null); // Omit exception as we're including it in the LogEvent
var template = new Serilog.Events.MessageTemplate(new[] { new Serilog.Parsing.TextToken(formattedMessage) });
var logEvent = new Serilog.Events.LogEvent(DateTimeOffset.Now, level, exception, template, Enumerable.Empty<Serilog.Events.LogEventProperty>());
_logger.ForContext("eventId", eventId).Write(logEvent);
return true;
}
}
}
}

Generate Bare Definitions for a Project or Namespace (Visual Studio)

In developing an SDK for use within our product, we want to provide users (developers) a Visual Studio plugin, mainly to provide them Intellisense during their development and ensure their code compiles for them. To do this, we strip the contents of all of our SDK APIs and put them all in a separate project.
For example:
public IEnumerable<string> AvailableConnections(bool querySystem) {
var connections = ConnectionList();
if(querySystem)
connections = connections.Concat(SystemConnections());
... // Filter connections somehow
return connections;
}
public void WriteToStream(Stream strFrom, Stream strTo) {
byte[] buffer = new byte[32 * 1024]; // 32 KiB
int len;
while ( (len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
Becomes:
public IEnumerable<string> AvailableConnections(bool querySystem) { return null; }
public void WriteToStream(Stream strFrom, Stream strTo) { }
My question: Does a tool exist to automate this, whether for a particular project or particular namespace? Ideally, it would intake a project or namespace and output all of the public classes/functions replacing their definitions with a simple return of the return type's default value. Visual Studio seems to do almost this when you view a class from which you don't have the source (e.g., you'll see IEnumerable<T> [from metadata]).
It sounds like you want to provide interfaces to your API.
You can build this into your project and essentially you will always have an assembly that shows all the public members without containing your implementation code.
Create a project that contains only the API, and reference that from your main project so that your concrete code (your implementation) implements the interfaces.
The API assembly would contain mostly interfaces and perhaps some abstract classes an helper, which you could share with developers.
Taking your example, you would have an interface like
public interface IMySdkThing
{
IEnumerable<string> AvailableConnections(bool querySystem);
void WriteToStream(Stream strFrom, Stream strTo);
}
Your implementation would be declared like:
public class MySdkThing : IMySdkThing
{
// all the code you showed, just as it is
}
All that said, it isn't clear how this will be useful to the developer. He or she will need a dll with some actual, executable code in it to use your library. Intellisense and compile-time checking come for free; you don't have to do anything special.

Resources